题意 https://www.luogu.org/problem/P4735 思路 考虑查询操作,假设 \(s[i]=a[1]\oplus a[2]\oplus ...\oplus a[i]\) ,那么原式等价于 \(s[p-1]\oplus s[n]\oplus x\) 的最大值。 我们可以维护一个可持久化trie树来解
题意
https://www.luogu.org/problem/P4735
思路
考虑查询操作,假设\(s[i]=a[1]\oplus a[2]\oplus ...\oplus a[i]\),那么原式等价于\(s[p-1]\oplus s[n]\oplus x\)的最大值。
我们可以维护一个可持久化trie树来解决。
还是需要给这份代码打上注释啊。。。
代码
#include <bits/stdc++.h> using namespace std; namespace StandardIO { template<typename T>inline void read (T &x) { x=0;T f=1;char c=getchar(); for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1; for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0'; x*=f; } template<typename T>inline void write (T x) { if (x<0) putchar('-'),x*=-1; if (x>=10) write(x/10); putchar(x%10+'0'); } } using namespace StandardIO; namespace Project { const int N=600600; // 之所以要开两倍是因为还有插入操作,两次RE都在这里。 int n,m; int s[N]; struct Trie { int tot; int root[N]; int ch[N*24][2],latest[N*24]; // latest数组用来限制左边界。 void insert (int left,int pos,int last,int cur) { latest[cur]=left; // 更新左边界。 if (pos==-1) return ; // 如果遍历完01串了就结束递归。 int o=(s[left]>>pos)&1; // 取出当前位。 if (last) ch[cur][o^1]=ch[last][o^1]; // 没有被更新的一遍原样继承即可。 ch[cur][o]=++tot; // 新建节点。 insert(left,pos-1,ch[last][o],ch[cur][o]); // 递归。 } int query (int left,int pos,int v,int cur) { // 按照贪心的思路向下走,每次尽量选取相反的孩子。 if (pos==-1) return s[latest[cur]]^v; // 返回答案。 int o=(v>>pos)&1; // 取出当前位。 if (latest[ch[cur][o^1]]>=left) return query(left,pos-1,v,ch[cur][o^1]); // 如果相反位可以取(即当前情况下存在),那么选择。 return query(left,pos-1,v,ch[cur][o]); // 否则选择相同位。 } } trie; inline void MAIN () { read(n),read(m); trie.latest[0]=-1,trie.root[0]=++trie.tot; trie.insert(0,23,0,trie.root[0]); for (register int i=1; i<=n; ++i) { read(s[i]),s[i]^=s[i-1]; trie.root[i]=++trie.tot,trie.insert(i,23,trie.root[i-1],trie.root[i]); } for (register int i=1; i<=m; ++i) { char op;int l,r,x; cin>>op; if (op=='A') { read(x),trie.root[++n]=++trie.tot,s[n]=s[n-1]^x; trie.insert(n,23,trie.root[n-1],trie.root[n]); } else { read(l),read(r),read(x); write(trie.query(l-1,23,s[n]^x,trie.root[r-1])),putchar('\n'); } } } } int main () { // freopen(".in","r",stdin); // freopen(".out","w",stdout); Project::MAIN(); }