P4735 最大異或和 題解
阿新 • • 發佈:2022-05-19
考慮異或可以表示成字首和的形式,則 \(a[p]\oplus a[p+1]\oplus\ldots \oplus a[n]\oplus x=s[p-1]\oplus s[n] \oplus x\)。後面都是知道的,所以可以拿著 \(s[n]\oplus x\) 的值去01-trie上做匹配。注意到還有一個 \(p\in[l-1,r-1]\) 的限制,可以使用可持久化trie,查詢第 \(r-1\) 個版本,再在每個節點記錄一個 \(las\) 表示走到這個點的 \(l\) 的最大值,只走其中 \(las\geq l-1\) 的即可。
點選檢視程式碼
#include<iostream> #include<cstdio> using namespace std; const int N=6e5+13,logN=21; int n,m,s[N],rt[N]; struct Trie{ int ch[N*logN][2],cnt,las[N*logN]; inline int insert(int num){ int now=rt[num-1],root=++cnt,p=root;las[p]=num; for(int i=24;i>=0;--i){ int c=(s[num]&(1<<i)?1:0); ch[p][c^1]=ch[now][c^1];ch[p][c]=++cnt; p=cnt,now=ch[now][c];las[p]=num; } return root; } inline int query(int l,int r,int x){ int p=rt[r];int res=0; if(!r) return x; for(int i=24;i>=0;--i){ int c=(x&(1<<i)?1:0); if(ch[p][c^1]&&las[ch[p][c^1]]>=l) p=ch[p][c^1],res+=(1<<i); else p=ch[p][c]; } return res; } }T; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%d",&s[i]); s[i]^=s[i-1]; rt[i]=T.insert(i); } while(m--){ char op;int l,r,x; cin>>op; if(op=='A'){ scanf("%d",&s[++n]); s[n]^=s[n-1]; rt[n]=T.insert(n); } else{ scanf("%d%d%d",&l,&r,&x); printf("%d\n",T.query(l-1,r-1,s[n]^x)); } } return 0; }