传送门
解析:
实际上这道题的做法非常直白。。。以及暴力。。。
思路:
考虑如果没有 a n d and and和 o r or or两个操作,只有 x o r xor xor的话,显然我们只需要维护一个 x o r t a g xortag xortag就可以轻松解决这个问题。
那么现在有了 a n d and and和 o r or or,这个问题就显得有点麻烦了。
考虑 a n d and and和 o r or or总是在不断地将不同的位变得相同。。。
所以我们只需要维护当前 A A A数列中所有数有哪些位置是已经全部相同了的。
然后每次有 a n d and and和 o r or or把本来不同的地方变得相同的时候,我们暴力重构 01 T r i e 01Trie 01Trie。
显然这样的重构不会超过 30 30 30次,直接做就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline char getalpha(){
re char c;
while(!isalpha(c=gc()));return c;
}
}
using namespace IO;
cs int N=50004,B=40;
int n,m,_1to=0x7fffffff,_0to=0,xortag;
int rt[N];
int son[N*(B+1)][2],siz[N*(B+1)],tot;
bool same[B+1];
int opt[B+1];
inline void insert(int pre,int now,int val){
for(int re i=30;~i;--i){
bool f=same[i]?0:((val>>i)&1);
siz[now]=siz[pre]+1;
son[now][!f]=son[pre][!f];
now=son[now][f]=++tot;
pre=son[pre][f];
}
siz[now]=siz[pre]+1;
}
int a[N];
inline void build(){
memset(siz,0,sizeof(int)*(tot+1));
memset(son,0,sizeof(int)*(tot+1)*2);
rt[0]=tot=1;
insert(0,rt[0],0);
for(int re i=1;i<=n;++i){
rt[i]=++tot;
insert(rt[i-1],rt[i],a[i]);
}
}
inline int query(int lt,int rt,int k){
int ans=0;
for(int re i=30;~i;--i){
if(same[i])ans|=opt[i]<<i,lt=son[lt][0],rt=son[rt][0];
else {
bool f=xortag&(1<<i);
int sze=siz[son[rt][f]]-siz[son[lt][f]];
if(sze>=k){
rt=son[rt][f];
lt=son[lt][f];
}
else {
k-=sze;
ans|=1<<i;
rt=son[rt][!f];
lt=son[lt][!f];
}
}
}
return ans;
}
signed main(){
n=getint(),m=getint();
for(int re i=1;i<=n;++i){
a[i]=getint();
_1to&=a[i];
_0to|=a[i];
}
for(int re i=0;i<=30;++i)same[i]=(_1to>>i)==(_0to>>i);
build();
while(m--){
char op=getalpha();
if(op=='A')op=getalpha();
switch(op){
case 'X':{
int x=getint();
xortag^=x;
for(int re i=0;i<=30;++i)if(same[i]&&(x&(1<<i)))opt[i]^=1;
break;
}
case 'n':{
int a=getint();
bool flag=0;
for(int re i=0;i<=30;++i)
if(!(a&(1<<i))){
if(same[i])opt[i]=0;
else {
flag=true;
same[i]=1;
opt[i]=0;
}
}
if(flag)build();
break;
}
case 'O':{
int o=getint();
bool flag=0;
for(int re i=0;i<=30;++i)
if(o&(1<<i)){
if(same[i])opt[i]=1;
else {
flag=true;
same[i]=1;
opt[i]=1;
}
}
if(flag)build();
break;
}
case 's':{
int l=getint(),r=getint(),k=getint();
cout<<query(rt[l-1],rt[r],k)<<"\n";
break;
}
}
}
return 0;
}