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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

CodeForces 282E Sausage Maximization(trie+xor)

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces 282E Sausage Maximization(trie+xor) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送題目
看了半個多小時的題解才搞明白,一下題解為自己的心得
參考博客(這兩個講的很詳細):
參考一
參考二

題意:有一個長度有n的整數序列,你要在這個序列中選擇一個前綴和后綴,前后綴不想交,前后綴任何一方都可以為空,問你前綴異或值與后綴異或值的異或最大是多少?
比如 一組數 1 2 3 4 5 6 你可以選擇前綴為1 2,前綴異或和為3 選擇后綴為4 5 6,后綴異或和為7
(前綴異或和)與(后綴異或和)異或值為4,但此時4并不是最大情況,求出最大情況

思路:
首先講個小例題:

給一個數 a,還有一堆數,怎么在這一堆數中找出一個數 b,a 和 b 的異或值最大?

最暴力的方法無疑是(老辦法) 枚舉,枚舉每一個b,但這樣肯定不行~~(不然我寫這個博客干什么)~~ ,想想計算機的本質是啥?對,二進制。我們把a與這堆數轉化成二進制,把后面這堆數裝進一個字典樹,當然要從最高位裝,比如這堆數是123456,如圖根據異或規則不同為一,所以我們要使a與b異或最大,就要讓b盡可能與a不同,a已經給定,b已經形成字典樹,我們就從字典樹root開始,盡量找出于a當前位置不同的數,直到找到最低位為止,那么這樣找到的b滿足條件。

回到這個題:
首先這些n個數組成一個區間w,w的全部異或結果是定值K,所以問題可以改成在區間w中取連續一段區間m,m的異或結果為X,m的前部分就成為區間w的前綴,后半部分就是區間w的后綴。
我們知道相同的數異或為零,那么X與K異或,重復的那部分區間異或后為零,就相當于是我們題目所求的
,所以就是求什么情況下X xor K最大。
發現現在的情況和一開始講的例題很像了吧,我們假設有個Y,Y與K的每一個二進制相異,我們就要讓X盡可能接近Y。
怎么實現呢?也是建一個字典樹,將f[i]放進去(f[i]=a[1] ^ a[2] ^ a[3] ^ …^ a[i]),那么f[i]^f[j]=a[i+1] ^ a[i+2] ^ … ^aj可以表示i+1到j這段區間的異或值。
我們枚舉區間m的結尾,每次用一個f[i]去匹配一個f[k],使得f[k]^f[i]的值在高位上盡可能去接近Y,這樣就相當于選出區間[k+1,i]de異或值作為X,每次在[1,i]區間內匹配出來一個最佳區間后,不斷更新答案。
看懂了嗎?這些神奇的操作,巧妙利用字典樹(工具人石錘)來匹配。
(太晚了就不重新打代碼了,借用下參考一的代碼)

//范圍是10的12次方,我們就將每個數固定為40位 #include<bits/stdc++.h> using namespace std; #define LL long long #define rep(i,j,k) for(int i = j; i <= k; i++ ) #define Rrep(i,j,k) for(int i = j; i >= k; i-- ) #define Clean(x,y) memset(x,y,sizeof(x)) int n; LL a[100009]; LL temp; LL ans;LL p[45]; int aim[45]; int Next[1000000][2]; int len; void init() {Clean(Next,0);len = 0; } void insert(LL t) {int now = 0;int k;Rrep(i,39,0){if ( p[i] & t ) k = 1;else k = 0;if ( !Next[now][k] ) Next[now][k] = ++len;now = Next[now][k];} }LL query(LL t) {int now = 0;LL ans = 0;int k;Rrep(i,39,0){if ( p[i] & t ) k = 1;else k = 0;if ( ( aim[i] && Next[now][1-k] ) || ( !aim[i] && Next[now][k] ) ){ans+=p[i];now = aim[i]==1?Next[now][1-k]:Next[now][k];}else now = aim[i]==0?Next[now][1-k]:Next[now][k];}return ans; }int main() {p[0] = 1;rep(i,1,40) p[i] = p[i-1]<<1;while(scanf("%d",&n)==1){a[0] = 0;ans = 0;rep(i,1,n){scanf("%I64d",&temp);a[i] = temp ^ a[i-1];}ans = max(ans,a[n]);rep(i,0,39)if ( a[n] & p[i] ) aim[i] = 0; //計算Yelse aim[i] = 1;init();insert(a[0]); rep(i,1,n){insert(a[i]);ans = max(ans,query(a[i]));}cout<<ans<<endl;}return 0; }

總結

以上是生活随笔為你收集整理的CodeForces 282E Sausage Maximization(trie+xor)的全部內容,希望文章能夠幫你解決所遇到的問題。

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