標籤:acm c++ codeforces 資料結構
題目大意:
給出一串數,pre[i](前i個數的異或)為a[0]~a[i-1]的異或,post[i](尾碼的異或)為a[i]~a[n-1]的異或,求pre[i]^post[j]的最大值(0<=i<=j<=n),其中,pre[0]=0,post[n]=0(表示一個數都不選)。
做法:利用trie樹將尾碼或者首碼儲存起來,首先從pre[n]開始,往前遍曆,對於每個首碼,將此時的尾碼添加到trie樹中,再在trie中尋找與當前首碼異或之後能得到最大的值。在trie中儲存數的時候,將該數的二進位的數位的每一位存進去,由於異或之後不可能增加位元,那麼我們要找最大的值的話,只需要從第一位開始,保證這一位能為1的時候取一,如果不能取一則取0,那麼最後的結果一定是最大的。這裡用的trie樹是非指標版的。。自己寫的,覺得指標太複雜(自己太弱....),用儲存節點下標的方式。
注意儲存數的時候,需要將40位全部存進去(2^40是大於10^12的第一個二次冪數),不然處理位元會很麻煩。這樣的話,trie樹中節點數最多也就40*10^5個,也是可行的。由於數的範圍是10^12,會爆int,得用long long ,
還得特別小心特別小心!像(1<<40)這樣的操作是會爆int的,必須寫成這樣(1LL<<40)才行。博主在這裡被坑了好久。。要不是大牛提醒的話,我都不知道什麼時候才能發現這個問題。。。推掉重寫也是有可能的!。。。
詳細見代碼和注釋:
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#define N 100010using namespace std;struct node{ long long nxt[2];//儲存nxt節點在數組中的下標}trie[N*40];long long all_idx,bit[42],num[N],n;long long createNode(){ memset(trie[all_idx].nxt,-1,sizeof(trie[all_idx].nxt));//沒有訪問過的置為-1 return all_idx++;}void insert_Node(long long root,long long cur){ memset(bit,0,sizeof(bit));//儲存cur的位元 long long len=0; while(cur) { bit[len++]=cur&1; cur>>=1; } long long idx=root; //將40位全部存進去 for(len=40;len>=0;len--) { long long k=bit[len]; if(trie[idx].nxt[k]==-1) trie[idx].nxt[k]=createNode(); idx=trie[idx].nxt[k]; }}long long running(long long root,long long cur){ long long sum=0; memset(bit,0,sizeof(bit)); long long len=0; while(cur) { bit[len++]=cur&1; cur>>=1; } long long idx=root; for(len=40;len>=0;len--) { long long k=!bit[len];/////兩個數不相同,異或結果為1 if(trie[idx].nxt[k]!=-1) { sum+=(1LL<<len);///////一定要加LL,被坑了好久。。。也是無語了 idx=trie[idx].nxt[k]; } else idx=trie[idx].nxt[!k];//如果不存在這樣的數,只能取0,並且從這邊走下去。 } return sum;}int main(){ scanf("%I64d",&n); long long pre=0,post=0; long long ans=0; for(long long i=0;i<n;i++) scanf("%I64d",num+i),pre^=num[i]; long long root=createNode(); for(long long i=n-1;i>=0;pre^=num[i],post^=num[i],i--) { insert_Node(root,post); ans=max(ans,running(root,pre)); } ans=max(ans,running(root,pre));//判斷取0個首碼的時候的值 cout<<ans<<endl; return 0;}
Codeforces 282E. Sausage Maximization【trie樹(非指標版)】