日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CodeForces - 1417E XOR Inverse(字典树求逆序对+分治)

發布時間:2024/4/11 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 1417E XOR Inverse(字典树求逆序对+分治) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出一個長度為 n 的數列 a,現在要求選出一個 x,將 a 中的每個元素都異或之后得到一個新的數列 b,要求數列 b 的逆序對最小,問最小的逆序對是多少,x 該如何選擇

題目分析:才知道字典樹上分治也可以求逆序對,時間復雜度是 nlogn 的,做法如下:

  • 將每個數都插入到字典樹中,記錄一下其下標
  • 對于某個節點來說,其左子樹中的點一定小于其右子樹中的點
  • 所以遍歷一遍左子樹中的點,雙指針找一下右子樹中有多少個點的下標大于當前枚舉的點,累加起來就是逆序對的個數了
  • 因為每一層最多有 n 個數,一共有 logn 層,所以遍歷的次數約等于 nlogn 次

    現在考慮該如何計算 x,假設 x 中的某一位為 0,那么在字典樹上將不產生影響,如果其中的某一位為 1 ,將對其對應層數的所有節點的左右子樹互換,注意這個過程中,只會影響到當前層數的逆序對,而不會影響到其他的層數的答案,換句話說,在這個題目中,x 中的每一位相互獨立

    再考慮如果 x 的某一位是 1 的話會造成什么影響,設原本的逆序對為 ans1,順序對為 ans2,如果將該層的左右子樹互換的話,那么 ans1 和 ans2 的值也會相應的被交換,所以我們可以對于每一層統計一下 dp[ deep ][ 0 ] 和 dp[ deep ][ 1 ] 分別表示當前層數中逆序對和順序對的個數,如果某一層的逆序對更少,顯然當前位填 0 更優,否則填 1 更優

    代碼:
    ?

    #pragma GCC optimize(2) #pragma GCC optimize("Ofast","inline","-ffast-math") #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=3e5+100;vector<int>node[N*40];int trie[N*40][2],cnt;LL dp[40][2];int newnode() {cnt++;trie[cnt][0]=trie[cnt][1]=0;node[cnt].clear();return cnt; }void insert(int x,int id) {int pos=0;for(int i=30;i>=0;i--){int to=(x>>i)&1;if(!trie[pos][to])trie[pos][to]=newnode();pos=trie[pos][to];node[pos].push_back(id);} }void dfs(int pos,int deep) {if(deep==-1)return;int lson=trie[pos][0],rson=trie[pos][1];LL res=0,r=0;int lsz=node[lson].size(),rsz=node[rson].size();for(int i=0;i<lsz;i++){while(r<rsz&&node[lson][i]>node[rson][r])r++;res+=r;}dp[deep][0]+=res;dp[deep][1]+=1LL*lsz*rsz-res;if(lson)dfs(lson,deep-1);if(rson)dfs(rson,deep-1); }void init() {cnt=-1;newnode(); }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);init();int n;scanf("%d",&n);for(int i=1;i<=n;i++){int num;scanf("%d",&num);insert(num,i);}dfs(0,30);LL ans=0,x=0;for(int i=0;i<=30;i++){if(dp[i][0]<=dp[i][1])ans+=dp[i][0];else{ans+=dp[i][1];x|=(1<<i);}}printf("%lld %lld\n",ans,x);return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的CodeForces - 1417E XOR Inverse(字典树求逆序对+分治)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。