题意:对一串数字进行抑或某数,和某数,或某数,统计某区间和的操作。
做法:对每一位进行统计。看了大神的代码之后才发现自己犯了个很2 的错误
#include<cstdio> #include<cstring> #define left l,m,x<<1 #define right m+1,r,x<<1|1 #define LMT 1000003 #define LL int int cov[4][LMT<<2],wei; int cover[4][LMT<<2],ox[4][LMT<<2]; //二进制数要记得算进去前面的0!!! //标记不要太复杂啊.... void init(void) { memset(cov,-1,sizeof(cov)); memset(cover,0,sizeof(cover)); } void fox(int l,int r,int x) { if(cover[wei][x]!=-1) cover[wei][x]^=1; else ox[wei][x]^=1; cov[wei][x]=r-l+1-cov[wei][x]; } void cut(int l,int r,int x) { //要更新了原先的状态肯定无法保持了。 int m=(l+r)>>1; if(cover[wei][x]!=-1) { int m=(l+r)>>1; cover[wei][x<<1]=cover[wei][x<<1|1]=cover[wei][x]; ox[wei][x<<1]=ox[wei][x<<1|1]=0; cov[wei][x<<1]=(m-l+1)*cover[wei][x<<1]; cov[wei][x<<1|1]=(r-m)*cover[wei][x<<1|1]; cover[wei][x]=-1; } if(ox[wei][x]) { fox(left),fox(right); ox[wei][x]=0; } } void update(char op,int L,int R,int l,int r,int x) { if(L<=l&&r<=R) { if(op==1) { cov[wei][x]=r-l+1; cover[wei][x]=1; ox[wei][x]=0; } if(op==0)ox[wei][x]=cov[wei][x]=cover[wei][x]=0;//这里... if(op==2)fox(l,r,x); return; } cut(l,r,x); int m=(l+r)>>1; if(L<=m)update(op,L,R,left); if(R>m)update(op,L,R,right); cov[wei][x]=cov[wei][x<<1]+cov[wei][x<<1|1]; } int sum(int L,int R,int l,int r,int x) { if(L<=l&&r<=R)return cov[wei][x]; cut(l,r,x); int m=(l+r)>>1,res=0; if(L<=m)res+=sum(L,R,left); if(R>m)res+=sum(L,R,right); return res; } int main(void) { int T; scanf("%d",&T); char ord[5]; while(T--) { init(); int n,m,x,l,r; LL res; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&x); wei=0; for(int j=0;j<4;j++)//这里 { if(x&(1<<j))update(1,i,i,1,n,1); else update(0,i,i,1,n,1); wei++; } } while(m--) { scanf("%s",ord); if(!strcmp(ord,"SUM")) { scanf("%d%d",&l,&r); l++;r++;res=0; for(wei=0;wei<4;wei++)res+=(1<<wei)*sum(l,r,1,n,1); printf("%d\n",res); } else { scanf("%d%d%d",&x,&l,&r); l++;r++; wei=0; for(int i=0;i<4;i++) { if(!strcmp(ord,"OR")&&(x&(1<<i)))update(1,l,r,1,n,1); if(!strcmp(ord,"XOR")&&(x&(1<<i)))update(2,l,r,1,n,1); if(!strcmp(ord,"AND")&&(~x&(1<<i)))update(0,l,r,1,n,1); wei++; } } } } return 0; }