题目
n(n<=1e5/1e6)个数,第i个数ai,ai范围[1,1e6]
m(m<=5e4/1e5)次操作,操作分四种
①区间异或x ②区间或x ③区间与x ④询问区间和
要参与操作的数x,范围[1,1e6]
题解
打一个标记即可,只是分类讨论会显得有点繁琐
按位压线段树,只有&0、|1和^1会起作用
标记分-1 0 1 2四种 分别代表没打标记 置零 置一 异或标记
&0和|1,都是强制置零或置一,异或标记更新时只有下列情况
1+异或=0,0+异或=1,没打标记+异或=异或,异或+异或=没打标记
心得
会但是没敲过完整版,补一下银川网络赛的代码
银川的(原)题交不了只好来这里交
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e6+10;
const int lg=4;
typedef long long ll;
int t,n,m,a[maxn];
char op[5];
int v,l,r;
struct node
{
int cs[lg+1],cov[lg+1];
node()
{
for(int i=lg;i>=0;--i)
cs[i]=0,cov[i]=-1;
}
}tree[maxn*4];
void pushup(int p)
{
for(int i=lg;i>=0;--i)
tree[p].cs[i]=tree[p<<1].cs[i]+tree[p<<1|1].cs[i];
}
void build(int p,int l,int r)
{
for(int i=lg;i>=0;--i)
{
tree[p].cs[i]=0;
tree[p].cov[i]=-1;
}
if(l==r)
{
for(int i=lg;i>=0;--i)
if(a[l]>>i&1)tree[p].cs[i]=1;
return;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
}
void pushdown(int i,int p,int l,int r)
{
if(~tree[p].cov[i])
{
int mid=(l+r)/2;
if(tree[p].cov[i]==1)
{
tree[p<<1].cs[i]=mid-l+1;
tree[p<<1|1].cs[i]=r-mid;
tree[p<<1].cov[i]=tree[p].cov[i];
tree[p<<1|1].cov[i]=tree[p].cov[i];
tree[p].cov[i]=-1;
}
else if(tree[p].cov[i]==0)
{
tree[p<<1].cs[i]=0;
tree[p<<1|1].cs[i]=0;
tree[p<<1].cov[i]=tree[p].cov[i];
tree[p<<1|1].cov[i]=tree[p].cov[i];
tree[p].cov[i]=-1;
}
else if(tree[p].cov[i]==2)
{
tree[p<<1].cs[i]=mid-l+1-(tree[p<<1].cs[i]);
tree[p<<1|1].cs[i]=r-mid-(tree[p<<1|1].cs[i]);
if(tree[p<<1].cov[i]==-1)tree[p<<1].cov[i]=2;
else if(tree[p<<1].cov[i]==0)tree[p<<1].cov[i]=1;
else if(tree[p<<1].cov[i]==1)tree[p<<1].cov[i]=0;
else if(tree[p<<1].cov[i]==2)tree[p<<1].cov[i]=-1;
if(tree[p<<1|1].cov[i]==-1)tree[p<<1|1].cov[i]=2;
else if(tree[p<<1|1].cov[i]==0)tree[p<<1|1].cov[i]=1;
else if(tree[p<<1|1].cov[i]==1)tree[p<<1|1].cov[i]=0;
else if(tree[p<<1|1].cov[i]==2)tree[p<<1|1].cov[i]=-1;
tree[p].cov[i]=-1;
}
}
}
void update(int p,int l,int r,int ql,int qr,int op,int v)
{
if(ql<=l&&r<=qr)
{
for(int i=lg;i>=0;--i)
{
if(op==1&&!(v>>i&1))//and
{
tree[p].cs[i]=0;
tree[p].cov[i]=0;
}
if(op==2&&(v>>i&1))//or
{
tree[p].cs[i]=r-l+1;
tree[p].cov[i]=1;
}
if(op==3&&(v>>i&1))//xor
{
tree[p].cs[i]=(r-l+1)-tree[p].cs[i];
if(tree[p].cov[i]==-1)tree[p].cov[i]=2;
else if(tree[p].cov[i]==0)tree[p].cov[i]=1;
else if(tree[p].cov[i]==1)tree[p].cov[i]=0;
else if(tree[p].cov[i]==2)tree[p].cov[i]=-1;
}
}
return;
}
for(int i=lg;i>=0;--i)
pushdown(i,p,l,r);
int mid=(l+r)>>1;
if(ql<=mid)update(p<<1,l,mid,ql,qr,op,v);
if(qr>mid)update(p<<1|1,mid+1,r,ql,qr,op,v);
pushup(p);
}
int aski(int i,int p,int l,int r,int ql,int qr)//第i位的个数
{
if(ql<=l&&r<=qr)return tree[p].cs[i];
pushdown(i,p,l,r);
int res=0;
int mid=(l+r)>>1;
if(ql<=mid)res+=aski(i,p<<1,l,mid,ql,qr);
if(qr>mid)res+=aski(i,p<<1|1,mid+1,r,ql,qr);
return res;
}
int ask(int p,int l,int r,int ql,int qr)//区间异或
{
int res=0;
for(int i=lg;i>=0;--i)
{
int num=aski(i,p,l,r,ql,qr);
res+=(1ll<<i)*num;
}
return res;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
build(1,1,n);
while(m--)
{
scanf("%s",op);
if(op[0]=='S')
{
scanf("%d%d",&l,&r);
l++;r++;
printf("%d\n",ask(1,1,n,l,r));
}
else if(op[0]=='X')
{
scanf("%d%d%d",&v,&l,&r);
l++;r++;
update(1,1,n,l,r,3,v);
}
else if(op[0]=='O')
{
scanf("%d%d%d",&v,&l,&r);
l++;r++;
update(1,1,n,l,r,2,v);
}
else if(op[0]=='A')
{
scanf("%d%d%d",&v,&l,&r);
l++;r++;
update(1,1,n,l,r,1,v);
}
}
}
return 0;
}
/*
1
4 6
1 2 4 7
SUM 0 2
XOR 5 0 0
SUM 0 2
OR 6 0 3
SUM 0 2
SUM 0 2
*/