Codeforces 242E XOR on Segment(线段树)
来源:互联网 发布:华硕笔记本推荐 知乎 编辑:程序博客网 时间:2024/06/05 17:04
题意:
给你n<=1e5个数a[i]和m<=5*1e4个操作,操作1要求输出[l,r]区间的数的和,操作2要求对[l,r]区间的数都去异或x。
思路:
线段树。对于异或操作,我们想到二进制数,只有当x的二进制位为1时,被异或的数对应的二进制位取反。对于求和操作,我们如果知道二进制数每位1的个数,我们累加起来就能得到其和了。所以这里对于每一位都建立一颗树来保存1的个数,这里a[i]、x<=1e6(2^20),所以我们需要建20棵树,然后只需要对每棵树进行简单的区间更新、区间求和即可。
#include<cstdio>typedef __int64 LL;const int MAX=1e5+5;int sum[25][MAX<<2],lazy[25][MAX<<2];int n,m,a[MAX];void PushUp(int id,int rt){sum[id][rt]=sum[id][rt<<1]+sum[id][rt<<1|1];}void PushDown(int id,int rt,int m){if(lazy[id][rt]){lazy[id][rt<<1]^=lazy[id][rt];lazy[id][rt<<1|1]^=lazy[id][rt];sum[id][rt<<1]=(m-(m>>1))-sum[id][rt<<1];sum[id][rt<<1|1]=(m>>1)-sum[id][rt<<1|1];lazy[id][rt]=0;}}void Build(int id,int l,int r,int rt){sum[id][rt]=lazy[id][rt]=0;if(l==r){sum[id][rt]=a[l]%2;a[l]/=2;//printf("l=%d a[l]=%d\n",l,a[l]);return;}int mid=(l+r)>>1;Build(id,l,mid,rt<<1);Build(id,mid+1,r,rt<<1|1);PushUp(id,rt);}void UpDate(int id,int L,int R,int l,int r,int rt){if(L<=l&&r<=R){lazy[id][rt]^=1;//printf("before: %d\n",sum[id][rt]);sum[id][rt]=(r-l+1)-sum[id][rt];//printf("after: %d\n",sum[id][rt]);//printf("l=%d r=%d\n",l,r);return;}PushDown(id,rt,r-l+1);int mid=(l+r)>>1;if(L<=mid) UpDate(id,L,R,l,mid,rt<<1);if(R>mid) UpDate(id,L,R,mid+1,r,rt<<1|1);PushUp(id,rt);}int Query(int id,int L,int R,int l,int r,int rt){if(L<=l&&r<=R){return sum[id][rt];}PushDown(id,rt,r-l+1);int res=0;int mid=(l+r)>>1;if(L<=mid) res+=Query(id,L,R,l,mid,rt<<1);if(R>mid) res+=Query(id,L,R,mid+1,r,rt<<1|1);return res;}int main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);}for(int i=1;i<=20;i++){Build(i,1,n,1);}scanf("%d",&m);int q,l,r,x;while(m--){scanf("%d",&q);if(q==1){scanf("%d%d",&l,&r);LL ans=0,tmp=1;for(int i=1;i<=20;i++){int cnt=Query(i,l,r,1,n,1);//printf("i=%d cnt=%d\n",i,cnt);ans+=(LL)cnt*tmp;tmp*=2;}printf("%I64d\n",ans);}else{scanf("%d%d%d",&l,&r,&x);for(int i=1;i<=20;i++){if(x%2){//printf("i=%d\n",i);UpDate(i,l,r,1,n,1);}x/=2;if(!x) break;}}}return 0;}
0 0
- Codeforces 242E XOR on Segment(线段树)
- CodeForces 242E - XOR on Segment 二维线段树?
- Codeforces 242E. XOR on Segment【线段树】
- CodeForces 242E XOR on Segment 二维线段树
- Codeforces 242E- XOR on Segment(线段树)
- Codeforces-242E:XOR on Segment(20个线段树)
- CF 242E XOR on Segment(二维线段树)
- codeforces 242E XOR on Segment
- Codeforces 242E(XOR on Segment)
- codeforces 242E - XOR on Segment
- CF 242E XOR on Segment 【线段树】
- CF 242E-XOR on Segment(线段树区间处理+二进制)
- Codeforce-242E-XOR on Segment(线段树区间更新)
- Codeforces Round #149 (Div. 2) E. XOR on Segment(21棵线段树处理每一位+区间异或)
- Codeforces #159 224 E E. XOR on Segment 二十几颗线段树 成段更新 成段求和
- CF 242E XOR on Segment
- CF242:XOR on Segment(线段树区间更新 & 二进制)
- Codeforces242E XOR on Segment(线段树)
- Linux CFS调度器之pick_next_task_fair选择下一个被调度的进程--Linux进程的管理与调度(二十八)
- 杭电 hdu 1070 Milk
- 算法竞赛入门经典第6章图论和树:竞赛选讲部分与习题
- Manacher算法--求最长回文子串
- redmine如何更改更换主题 (redmine之三)
- Codeforces 242E XOR on Segment(线段树)
- [个人学习]另一个 Promise 对象
- eCryptfs - read/write系统调用
- 让程序在崩溃时体面的退出之SEH
- Linux 下GNU Readline库函数安装用于实现shell内嵌补全
- c#之线程
- 在实际例子中学习正则表达式
- 对于异常的捕捉
- poj 1190 生日蛋糕