若想要深刻學習可持久化0-1Trie樹,傳送門。html
Description:c++
給定數列 \(\{a_n\}\) ,支持兩種操做:學習
\[ \max_{i=l}^{r}\left \{\left(\bigoplus_{j=i}^{n}a_j \right)\bigoplus x\right \} \]ui
Method:spa
定義 \(Xorsum_i\) 爲 \(\bigoplus_{i=1}^{n}a_i\) ,即前綴異或和。咱們顯然能夠獲得
\[ \left(\bigoplus_{i=pos}^{n}a_i\right)\bigoplus x=Xorsum_{pos-1}\bigoplus Xorsum_n \bigoplus x \]code
注:\(x\bigoplus x=0\) , \(x \bigoplus 0=x\)htm
咱們發現 \(Xorsum_n\bigoplus x\) 是一個定值,咱們只須要維護 \(Xorsum_{pos-1}\) 便可。blog
考慮用可持久化0-1Trie樹維護。與主席樹思路相同 ,咱們創建 \(n+1\) 個版本的0-1Trie樹,查詢的時候運用貪心的思路便可。ip
可持久化線段樹一樣支持「前綴和」的思想,咱們最後只須要在第 \(r\) 個版本的0-1Trie樹上查找 \(l\) 位置便可。element
本題毒瘤卡常,本人人醜常數大,用了fread
等各類卡常操做才經過。而且因爲luogu評測姬的緣由(大霧,已經經過的代碼又會T掉woc。卡不過的話,開o2
吧。
Code:
#include<bits/stdc++.h> #define Maxn 600010 #define Maxdep 23 #define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) char buf[1<<21],*p1=buf,*p2=buf; inline void read(int &x) { int f=1;x=0;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} x*=f; } int n,m; int sum[Maxn]; struct trie { trie *chd[2]; int symbl; trie() { for(int i=0;i<2;i++) chd[i]=NULL; symbl=0; } }*root[Maxn],tree[Maxn<<5],*tail; void Init(){tail=tree;} void build(trie *&p,int dep) { p=new (tail++)trie(); if(dep<0) return ; build(p->chd[0],dep-1); } void update(trie *&p,trie *flag,int dep,int i) { p=new (tail++)trie(); if(flag) *p=*flag; if(dep<0) return (void)(p->symbl=i); int tmp=(sum[i]>>dep)&1;//判斷是1仍是0 if(!tmp) update(p->chd[0],flag?flag->chd[0]:NULL,dep-1,i); else update(p->chd[1],flag?flag->chd[1]:NULL,dep-1,i); if(p->chd[0]) p->symbl=std::max(p->symbl,p->chd[0]->symbl); if(p->chd[1]) p->symbl=std::max(p->symbl,p->chd[1]->symbl); } int query(trie *p,int x,int dep,int limit) { if(dep<0) return sum[p->symbl]^x; int tmp=(x>>dep)&1; if(p->chd[tmp^1]&&p->chd[tmp^1]->symbl>=limit) return query(p->chd[tmp^1],x,dep-1,limit); return query(p->chd[tmp],x,dep-1,limit); } signed main() { Init(); read(n),read(m); build(root[0],Maxdep); for(int i=1,x;i<=n;i++) { read(x); sum[i]=sum[i-1]^x; update(root[i],root[i-1],Maxdep,i); } for(int i=1;i<=m;i++) { char ch=getchar(); while(ch!='A'&&ch!='Q') ch=getchar(); if(ch=='A') { int x; read(x); n++; sum[n]=sum[n-1]^x; update(root[n],root[n-1],Maxdep,n); continue; } if(ch=='Q') { int l,r,x; read(l),read(r),read(x); int ans=query(root[r-1],sum[n]^x,Maxdep,l-1); printf("%d\n",ans); continue; } } return 0; }