FZU 2105 Digits Count 区间更新
2015-07-20 18:00
309 查看
题意:有四个操作
1. l r v,对于[l,r]区间内的所有数都和v按位且(a[i]=a[i]&v)
2. l r v,对于[l,r]区间内的所有数都和v按位或(a[i]=a[i]|v)
3. l r v,对于[l,r]区间内的所有数都和v按位异或(a[i]=a[i]^v)
4. l r,对于[l,r]区间内的数求和
但是数据很小,所有的数和被操作数都是4位的,所以只需要统计每一位的1的个数就行。
但是需要注意的地方
且操作:如果对应位为0,那么就是区间赋值为0
或操作:如果对应位为1,那么就是区间赋值为1
异或操作:若对应位为1,那么区间内1的数量变为0的数量,区间内的1和0的数量互换
假设且操作和异或操作为op1
假设异或操作为op2
op1和op2的操作顺序需要考虑:
若当前节点为op1、子节点为op1,那么无意义,op1直接覆盖
若当前节点为op1、子节点为op2,op1直接覆盖
若当前节点为op2、子节点为op1,那么子节点op1的结果影响op2,所以先把子节点的op1推向子节点的子节点
若当前节点为op2、子节点为op2,这种情况有点复杂,其实画画图就可以得出,某个节点更新两遍之后值是不变的,所以设立一个标记,表示下一个节点是否需要更新,如果下一个节点需要被op2,那么值为1,下一个节点的值^1,以此传递下去。其实自己思考思考比较好。
代码:
1. l r v,对于[l,r]区间内的所有数都和v按位且(a[i]=a[i]&v)
2. l r v,对于[l,r]区间内的所有数都和v按位或(a[i]=a[i]|v)
3. l r v,对于[l,r]区间内的所有数都和v按位异或(a[i]=a[i]^v)
4. l r,对于[l,r]区间内的数求和
但是数据很小,所有的数和被操作数都是4位的,所以只需要统计每一位的1的个数就行。
但是需要注意的地方
且操作:如果对应位为0,那么就是区间赋值为0
或操作:如果对应位为1,那么就是区间赋值为1
异或操作:若对应位为1,那么区间内1的数量变为0的数量,区间内的1和0的数量互换
假设且操作和异或操作为op1
假设异或操作为op2
op1和op2的操作顺序需要考虑:
若当前节点为op1、子节点为op1,那么无意义,op1直接覆盖
若当前节点为op1、子节点为op2,op1直接覆盖
若当前节点为op2、子节点为op1,那么子节点op1的结果影响op2,所以先把子节点的op1推向子节点的子节点
若当前节点为op2、子节点为op2,这种情况有点复杂,其实画画图就可以得出,某个节点更新两遍之后值是不变的,所以设立一个标记,表示下一个节点是否需要更新,如果下一个节点需要被op2,那么值为1,下一个节点的值^1,以此传递下去。其实自己思考思考比较好。
代码:
//author: CHC //First Edit Time: 2015-07-19 22:56 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <vector> #include <map> #include <queue> #include <set> #include <algorithm> #include <limits> using namespace std; typedef long long LL; const int MAXN=1000000+1000; const int INF = numeric_limits<int>::max(); const LL LL_INF= numeric_limits<LL>::max(); #define lson L,mid,rt<<1 #define rson mid+1,R,rt<<1|1 struct Tree { int cnt[4]; int flag[4]; bool v[4]; }tr[MAXN<<2]; void pushup(int rt){ for(int i=0;i<4;i++){ tr[rt].cnt[i]=tr[rt<<1].cnt[i]+tr[rt<<1|1].cnt[i]; } } void pushdownA(int L,int R,int rt); void pushdownB(int L,int R,int rt); void pushdownC(int L,int R,int rt); void pushdownA(int L,int R,int rt){ if(L==R)return ; int mid=(L+R)>>1; for(int i=0;i<4;i++){ if(tr[rt].flag[i]&1){ tr[rt<<1].cnt[i]=(mid-L+1); tr[rt<<1|1].cnt[i]=(R-(mid+1)+1); tr[rt<<1].flag[i]=tr[rt<<1|1].flag[i]=tr[rt].flag[i]; tr[rt].flag[i]=0; tr[rt].v[i]=0; } } } void pushdownB(int L,int R,int rt){ if(L==R)return ; //int mid=(L+R)>>1; for(int i=0;i<4;i++){ if(tr[rt].flag[i]&2){ tr[rt<<1].cnt[i]=0; tr[rt<<1|1].cnt[i]=0; tr[rt<<1].flag[i]=tr[rt<<1|1].flag[i]=tr[rt].flag[i]; tr[rt].flag[i]=0; tr[rt].v[i]=0; } } } void pushdownC(int L,int R,int rt){ int mid=(L+R)>>1; for(int i=0;i<4;i++){ if(tr[rt].flag[i]&4){ if(tr[rt<<1].flag[i]&1)pushdownA(lson); if(tr[rt<<1].flag[i]&2)pushdownB(lson); if(tr[rt<<1|1].flag[i]&1)pushdownA(rson); if(tr[rt<<1|1].flag[i]&2)pushdownB(rson); if(tr[rt].v[i]){ tr[rt<<1].cnt[i]=mid-L+1-tr[rt<<1].cnt[i]; tr[rt<<1|1].cnt[i]=R-(mid+1)+1-tr[rt<<1|1].cnt[i]; tr[rt<<1].v[i]^=1; tr[rt<<1|1].v[i]^=1; } tr[rt<<1].flag[i]=tr[rt<<1|1].flag[i]=tr[rt].flag[i]; tr[rt].flag[i]=0; tr[rt].v[i]=0; } } } void pushdown(int L,int R,int rt){ if(L==R)return ; pushdownA(L,R,rt); pushdownB(L,R,rt); pushdownC(L,R,rt); } int A[MAXN]; void build(int L,int R,int rt){ memset(&tr[rt],0,sizeof(Tree)); if(L==R){ for(int i=0;i<4;i++) tr[rt].cnt[i]=(A[L]>>i)&1; return ; } int mid=(L+R)>>1; build(lson);build(rson); pushup(rt); } void update(int L,int R,int rt,int l,int r,int flag,int pos){ pushdown(L,R,rt); if(l<=L&&R<=r){ if(flag&1){ tr[rt].cnt[pos]=(R-L+1); tr[rt].flag[pos]=flag; } if(flag&2){ tr[rt].cnt[pos]=0; tr[rt].flag[pos]=flag; } if(flag&4){ tr[rt].cnt[pos]=(R-L+1)-tr[rt].cnt[pos]; tr[rt].flag[pos]=flag; tr[rt].v[pos]=1; } return ; } int mid=(L+R)>>1; if(l<=mid)update(lson,l,r,flag,pos); if(r>mid)update(rson,l,r,flag,pos); pushup(rt); return ; } int query(int L,int R,int rt,int l,int r,int pos){ pushdown(L,R,rt); if(l<=L&&R<=r)return tr[rt].cnt[pos]; int mid=(L+R)>>1,ans=0; if(l<=mid)ans+=query(lson,l,r,pos); if(r>mid)ans+=query(rson,l,r,pos); pushup(rt); return ans; } int main() { int t,n,m; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&A[i]); build(1,n,1); char strs[10]; for(int i=0,l,r,v;i<m;i++){ scanf(" %s",strs); if(strs[0]=='S'){ scanf("%d%d",&l,&r); ++l;++r; int ans=query(1,n,1,l,r,0)+query(1,n,1,l,r,1)*2+query(1,n,1,l,r,2)*4+query(1,n,1,l,r,3)*8; printf("%d\n",ans); } if(strs[0]=='X'){ scanf("%d%d%d",&v,&l,&r); ++l;++r; for(int i=0;i<4;i++){ if((v>>i)&1)update(1,n,1,l,r,4,i); } } if(strs[0]=='O'){ scanf("%d%d%d",&v,&l,&r); ++l;++r; for(int i=0;i<4;i++){ if((v>>i)&1)update(1,n,1,l,r,1,i); } } if(strs[0]=='A'){ scanf("%d%d%d",&v,&l,&r); ++l;++r; for(int i=0;i<4;i++){ if(((v>>i)&1)==0)update(1,n,1,l,r,2,i); } } } } return 0; }