与或异或线段树
Posted bxd123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了与或异或线段树相关的知识,希望对你有一定的参考价值。
题意:
对区间进行异或 与 或操作 和询问区间和
对每一位开一棵线段树即可
#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\n",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;
以上是关于与或异或线段树的主要内容,如果未能解决你的问题,请参考以下文章