题意:
对区间进行异或 与 或操作 和询问区间和
对每一位开一棵线段树即可
#include<cstdio> #include<iostream> #include<cstring> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=1e5+100; int n,m; ll t[25][N<<2],colfan[25][N<<2],col[25][N<<2],a[N]; void up(int id,int pos) { t[id][pos]=t[id][pos<<1]+t[id][pos<<1|1]; } void down(int id,int pos,int l,int r) { int mid=(l+r)>>1; if(col[id][pos]!=-1) { colfan[id][pos<<1]=colfan[id][pos<<1|1]=0; col[id][pos<<1]=col[id][pos<<1|1]=col[id][pos]; t[id][pos<<1]=1ll*(mid-l+1)*col[id][pos]; t[id][pos<<1|1]=1ll*(r-mid)*col[id][pos]; col[id][pos]=-1; } if(colfan[id][pos]==1) { colfan[id][pos]=0; colfan[id][pos<<1]^=1; colfan[id][pos<<1|1]^=1; t[id][pos<<1]=1ll*(mid-l+1)-t[id][pos<<1]; t[id][pos<<1|1]=1ll*(r-mid)-t[id][pos<<1|1]; } } void build(int id,int l,int r,int pos) { col[id][pos]=-1;colfan[id][pos]=0; if(l==r) { t[id][pos]=( (a[l]>>id)&1 ); col[id][pos]=0;return ; } int m=(l+r)>>1; build(id,l,m,pos<<1);build(id,m+1,r,pos<<1|1); up(id,pos); } void upfan(int id,int L,int R,int l,int r,int pos) { if(L<=l&&r<=R) { t[id][pos]=(r-l+1)-t[id][pos]; colfan[id][pos]^=1; return ; } int m=(l+r)>>1;down(id,pos,l,r); if(L<=m)upfan(id,L,R,l,m,pos<<1); if(R>m)upfan(id,L,R,m+1,r,pos<<1|1); up(id,pos); } void upsum(int id,int L,int R,int v,int l,int r,int pos) { if(L<=l&&r<=R) { t[id][pos]=(r-l+1)*v; col[id][pos]=v;colfan[id][pos]=0; return ; } down(id,pos,l,r); int m=(l+r)>>1; if(L<=m)upsum(id,L,R,v,l,m,pos<<1); if(R>m)upsum(id,L,R,v,m+1,r,pos<<1|1); up(id,pos); } ll qsum(int id,int L,int R,int l,int r,int pos) { if(L<=l&&r<=R)return t[id][pos]; int m=(l+r)>>1;ll ans=0;down(id,pos,l,r); if(L<=m)ans+=qsum(id,L,R,l,m,pos<<1); if(R>m)ans+=qsum(id,L,R,m+1,r,pos<<1|1); return ans; } int main() { CLR(col,-1); rep(i,1,n)scanf("%lld",&a[i]); rep(i,0,22)build(i,1,n,1); scanf("%d",&m); ll op,l,r,x; while(m--) { scanf("%lld",&op); if(op==1) { scanf("%lld%lld",&l,&r); ll ans=0; rep(i,0,22) ans+=1ll*qsum(i,l,r,1,n,1)*(1ll<<i); printf("%lld ",ans); } else if(op==2) { scanf("%lld%lld%lld",&l,&r,&x); rep(i,0,22) if( (x>>i)&1 ) upfan(i,l,r,1,n,1); } else if(op==3) { scanf("%lld%lld%lld",&l,&r,&x); rep(i,0,22) if( (x>>i)&1 ) upsum(i,l,r,1,1,n,1); } else if(op==4) { scanf("%lld%lld%lld",&l,&r,&x); rep(i,0,22) if( ((x>>i)&1)==0 ) upsum(i,l,r,0,1,n,1); } } return 0; }