【描述】
请你维护一个线段树
支持一下操作
A x l r 区间 and x
O x l r区间 Or x
X x l r 区间 Xor x
S l r 区间求和
【输入】
一个数T,表示数据组数。 一个数n表示初始序列长,m表示查询。 随后n个整数。接下来m次询问, 如上。
【思路】
我们注意到
很小,而位运算每一位独立,所以我们可以维护4棵线段树,分别维护每一位即可。上述操作就变成了区间01取反,区间01覆盖,区间求和。注意lazy标记之间的关系。就是这道题,我把输入看错了,对拍了一个小时都没错,一脸懵逼,果然,有一种错误是对拍发现不了的。
代码:
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define re register
#define lc (p<<1)
#define rc (p<<1|1)
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
int n,m,a[N],b,c;
inline int red(){
int data=0;int w=1; char ch=0;
ch=getchar();
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return data*w;
}
struct tree{
int sum[N<<2|1],cover[N<<2|1],ls[N<<2|1],rs[N<<2|1];
bool rev[N<<2|1];int id;
inline int len(const int &p){return rs[p]-ls[p]+1;}
void pushdown();
void pushup(const int &p){pushdown(p);sum[p]=sum[lc]+sum[rc];}
void pushcover(const int &p,const int &x)
{
if(rev[p])rev[p]=0;
cover[p]=x;sum[p]=len(p)*x;
}
void pushrev(const int &p)
{
if(cover[p]!=-1)cover[p]^=1;
else rev[p]^=1;
sum[p]=len(p)-sum[p];
}
void pushdown(const int &p){
if(cover[p]!=-1)pushcover(lc,cover[p]),pushcover(rc,cover[p]),cover[p]=-1;
if(rev[p])pushrev(lc),pushrev(rc),rev[p]=0;
}
void build(int p,int l,int r)
{
ls[p]=l,rs[p]=r;rev[p]=0;cover[p]=-1;
if(l==r)return (void)(sum[p]=(bool)(a[l]&(1<<id)));
int mid=(l+r)>>1;build(lc,l,mid);build(rc,mid+1,r);
pushup(p);
}
void cor(int p,const int &ql,const int &qr,const int &x){
pushdown(p);
if(ql<=ls[p]&&rs[p]<=qr)return pushcover(p,x);
int mid=(ls[p]+rs[p])>>1;
if(ql<=mid)cor(lc,ql,qr,x);
if(qr>mid)cor(rc,ql,qr,x);
pushup(p);
}
void rvs(int p,const int &ql,const int &qr){
pushdown(p);
if(ql<=ls[p]&&rs[p]<=qr)return pushrev(p);
int mid=(ls[p]+rs[p])>>1;
if(ql<=mid)rvs(lc,ql,qr);
if(qr>mid)rvs(rc,ql,qr);
pushup(p);
}
int query(int p,const int &ql,const int &qr){
pushdown(p);
if(ql<=ls[p]&&rs[p]<=qr)return sum[p];
int mid=(ls[p]+rs[p])>>1;
int ans=0;
if(ql<=mid)ans+=query(lc,ql,qr);
if(qr>mid)ans+=query(rc,ql,qr);
return ans;
}
}sgt[4];
int l,r,x,ans;
char s;
int main(){
int T=red();
for(int re i=0;i^4;i++)sgt[i].id=i;
while(T--){
n=red();m=red();
for(int re i=1;i<=n;++i)a[i]=red();
for(int re i=0;i^4;i++)sgt[i].build(1,1,n);
while(m--){
scanf("\n%c",&s);
if(s!='S')x=red();
l=red()+1;r=red()+1;
if(s=='S'){
ans=0;
for(int re i=0;i^4;i++)ans+=sgt[i].query(1,l,r)<<i;
printf("%d\n",ans);
continue;
}
for(int re i=0;i^4;i++){
if(x&(1<<i)){
if(s=='O')sgt[i].cor(1,l,r,1);
if(s=='X')sgt[i].rvs(1,l,r);
}
else if(s=='A')sgt[i].cor(1,l,r,0);
}
}
}
}