BZOJ3261:最大異或和
阿新 • • 發佈:2019-02-28
truct %s continue 由於 代碼 只需要 我們 == lin 的合適的值就行了。
淺談\(Trie\):https://www.cnblogs.com/AKMer/p/10444829.html
題目傳送門:https://lydsy.com/JudgeOnline/problem.php?id=3261
假設現在所有數的異或和是\(xor\_sum\),\(sum\_xor[i]\)表示前\(i\)個數的異或和,那麽每次詢問可以轉化成:
在區間\([l-1,r-1]\)裏面找一個\(sum\_xor_i\),使得\(sum\_xor_i\oplus x\oplus xor\_sum\)最大值。
我們已經知道了\(x\oplus xor\_sum\)的值,只需要按照每一位去貪心地找\(sum\_xor_i\)
由於是在區間內找有沒有某一位存在我想要的,顯然就能想到可持久化了。
時間復雜度:\(O((n+m)*24)\)
空間復雜度:\(O((n+m)*24)\)
代碼如下:
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int maxn=3e5+5; char s[5]; int rt[maxn<<1]; int cnt,n,m,xor_sum; int read() { int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } struct Trie { int tot; struct node { int sum; int son[2]; }p[maxn*48]; void ins(int lst_id,int id,int v) { int lst=rt[lst_id],u; u=rt[id]=++tot; for(int i=24;~i;i--) { int c=v>>i&1; p[u].son[c]=++tot; u=p[u].son[c],lst=p[lst].son[c]; p[u]=p[lst];p[u].sum++; } } void make_ans(int u2,int u1,int v) { int ans=0; for(int i=24;~i;i--) { int c=v>>i&1; int sum=p[p[u1].son[c^1]].sum; sum-=p[p[u2].son[c^1]].sum; if(!sum)ans=ans<<1,u1=p[u1].son[c],u2=p[u2].son[c]; else ans=ans<<1|1,u1=p[u1].son[c^1],u2=p[u2].son[c^1]; } printf("%d\n",ans); } }T; int main() { cnt=n=read(),m=read(); for(int i=1;i<=n;i++) { int x=read();xor_sum^=x; T.ins(i-1,i,xor_sum); } for(int i=1;i<=m;i++) { scanf("%s",s+1); if(s[1]=='A') { int x=read();xor_sum^=x,cnt++; T.ins(cnt-1,cnt,xor_sum); } else { int l=read(),r=read(),x=read(); if(r==1) {printf("%d\n",x^xor_sum);continue;} T.make_ans(rt[max(0,l-2)],rt[r-1],x^xor_sum); } } return 0; }
BZOJ3261:最大異或和