题目链接就不挂了,服务器受不了
l r
: Calculate the sum of current array elements on the segment [l,r], that is, count value a[l] + a[l+1] +...+a[r].l r x
: Apply the xor(^) operation of the given number x to each array element on segment [l, r]l r x
: Apply the or(|) operation of the given number x to each array element on segment [l, r]l r x
: Apply the and(&) operation of the given number x to each array element on segment [l, r] You've got a list of m operations of the indicated type. Your task is to perform all given operations, for each sum query you should print the result you get.
给的数字是1e6所以开22棵线段树,每一棵线段树保存的是一个二进制位,对于二进制异或来说,只有二进制1会影响值的改变,有1的变0,有0的变1,。
对于二进制与来说,只有二进制0会影响结果,并且还会覆盖异或(^),或 (|) 的作用
对于二进制或来说,只有二进制1会影响结果,并且还会覆盖异或(^),或 (|) 的作用
那么如果是异或,对于每个二进制1,就让相应的区间取反,
如果是或,对于每个二进制1,就让相应的区间全变1
如果是与,对于每个二进制0,就让相应的区间全变0
具体看代码
#include <cstdio>
using namespace std;
typedef long long ll;
const int MAX = 1e5+10;
typedef struct{
ll sum,lazy;
}Point;
int n,m;
ll a[MAX];
Point tree[25][MAX<<2];
void PushUp(int id,int root){
tree[id][root].sum=tree[id][root<<1].sum+tree[id][root<<1|1].sum;
}
void PushDown(int id,int root,int l,int r){
if(tree[id][root].lazy==1){
tree[id][root].lazy=0;
tree[id][root<<1].lazy^=1;
tree[id][root<<1|1].lazy^=1;
int mid = (l+r)>>1;
tree[id][root<<1].sum=(mid-l+1)-tree[id][root<<1].sum;
tree[id][root<<1|1].sum=(r-mid)-tree[id][root<<1|1].sum;
}
else if(tree[id][root].lazy==-1){
tree[id][root].lazy=0;
tree[id][root<<1].lazy=-1;
tree[id][root<<1|1].lazy=-1;
int mid = (l+r)>>1;
tree[id][root<<1].sum=0;
tree[id][root<<1|1].sum=0;
}
else if(tree[id][root].lazy==-2){
tree[id][root].lazy=0;
tree[id][root<<1].lazy=-2;
tree[id][root<<1|1].lazy=-2;
int mid = (l+r)>>1;
tree[id][root<<1].sum=(mid-l+1);
tree[id][root<<1|1].sum=(r-mid);
}
}
void build(int id,int l,int r,int root)
{
if(l==r){
tree[id][root].sum=((a[l]>>id)&1);
tree[id][root].lazy=0;
return;
}
int mid = (l+r)>>1;
build(id,l,mid,root<<1);
build(id,mid+1,r,root<<1|1);
PushUp(id,root);
return;
}
void update(int id,int L,int R,int l,int r,int root){//xor
if(L<=l&&r<=R){
tree[id][root].sum=(r-l+1)-tree[id][root].sum;
if(tree[id][root].lazy > 0)
tree[id][root].lazy^=1;
else
tree[id][root].lazy^=1;
return;
}
int mid = (l+r)>>1;
PushDown(id,root,l,r);
if(L<=mid) update(id,L,R,l,mid,root<<1);
if(R>mid) update(id,L,R,mid+1,r,root<<1|1);
PushUp(id,root);
}
void update1(int id,int L,int R,int l,int r,int root){// or
if(L<=l&&r<=R){
tree[id][root].sum=(r-l+1);
tree[id][root].lazy=-2;
return;
}
int mid = (l+r)>>1;
PushDown(id,root,l,r);
if(L<=mid) update1(id,L,R,l,mid,root<<1);
if(R>mid) update1(id,L,R,mid+1,r,root<<1|1);
PushUp(id,root);
}
void update2(int id,int L,int R,int l,int r,int root){//and
if(L<=l&&r<=R){
tree[id][root].sum=0;
tree[id][root].lazy = -1;
return;
}
int mid = (l+r)>>1;
PushDown(id,root,l,r);
if(L<=mid) update2(id,L,R,l,mid,root<<1);
if(R>mid) update2(id,L,R,mid+1,r,root<<1|1);
PushUp(id,root);
}
ll query(int id,int L,int R,int l,int r,int root){
if(L<=l&&r<=R) return tree[id][root].sum;
int mid = (l+r)>>1;
PushDown(id,root,l,r);
ll ans=0;
if(L<=mid) ans+=query(id,L,R,l,mid,root<<1);
if(R>mid) ans+=query(id,L,R,mid+1,r,root<<1|1);
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=0;i<=22;i++) build(i,1,n,1);
scanf("%d", &m);
while(m--){
ll op,l,r,k, ans;
scanf("%lld",&op);
if(op==1){
scanf("%lld%lld",&l,&r); ans=0;
for(int i=0;i<=22;i++) ans+=1ll*query(i,l,r,1,n,1)*(1ll<<i);
printf("%lld\n",ans);
}
else if(op == 2){
scanf("%lld%lld%lld",&l,&r,&k);
for(int i=0;i<=22;i++) if((k>>i)&1) update(i,l,r,1,n,1);
}
else if(op == 3){
scanf("%lld%lld%lld",&l,&r,&k);
for(int i=0;i<=22;i++) if((k>>i)&1) update1(i,l,r,1,n,1);
}
else {
scanf("%lld%lld%lld",&l,&r,&k);
for(int i=0;i<=22;i++) if(!((k>>i)&1)) update2(i,l,r,1,n,1);
}
}
return 0;
}