题面

长度为\(n\)的数列,现有两种操作:

1、区间异或操作

2、区间求和操作

对于每个查询,输出答案

思路:

线段树+二进制拆位

线段树区间修改一般使用的都是懒标记的方法,但是对于异或,懒标记的方法显然是行不通的,于是就考虑二进制拆位

主要的思路就是将一个数,拆成若干个二进制位,然后对于异或操作,就转换成了每一位上异或操作

分类讨论一下:

1、当\(x\)的第\(i\)位为\(1\)时,\(1\ xor\ 0=1\),\(1\ xor\ 1=0\)

也就是看成区间取反操作

2、当\(x\)的第\(i\)位为\(0\)时,\(0\ xor\ 0=0\),\(0\ xor\ 1=1\)

也就是说操作前后没有变化,所以就不执行修改操作

Code:

#include<bits/stdc++.h>
#define ll long long
#define N 100010
using namespace std;
int n,a[N],res,L,R,T,x;
int f[N<<2][25],tag[N<<2][25];//1e6<2^20
ll b[25],ans;//别忘记long long
int read(){ int s=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)){s=(s<<1)+(s<<3)+c-'0';c=getchar();}
return s;
}
void built(int k,int l,int r)
{
if(l>r) return;
if(l==r)
{
res=a[l];
for(int i=0;i<21;i++)//拆位
if((res>>i)&1) f[k][i]=1;
return;
}
int mid=(l+r)>>1,cur=k<<1;
built(cur,l,mid);
built(cur|1,mid+1,r);
for(int i=0;i<21;i++)
f[k][i]=f[cur][i]+f[cur|1][i];
return;
}
void push(int k,int l,int r,int p)//p表示第几位
{
f[k][p]=(r-l+1)-f[k][p];//区间取反
if(l!=r)
{
int cur=k<<1;
tag[cur][p]^=1;
tag[cur|1][p]^=1;
}
tag[k][p]=0;
}
void Modify(int k,int l,int r,int p)//p同上
{
if(tag[k][p]) push(k,l,r,p);
if(r<L||R<l) return;
if(L<=l&&r<=R)
{
push(k,l,r,p);
return;
}
int mid=(l+r)>>1,cur=k<<1;
Modify(cur,l,mid,p);
Modify(cur|1,mid+1,r,p);
f[k][p]=f[cur][p]+f[cur|1][p];
}
void Query(int k,int l,int r)//查询,所有位的懒标记都要下放
{
for(int i=0;i<21;i++)
if(tag[k][i]) push(k,l,r,i);
if(r<L||R<l) return;
if(L<=l&&r<=R)
{
for(int i=0;i<21;i++) ans+=f[k][i]*b[i];
return;
}
int mid=(l+r)>>1,cur=k<<1;
Query(cur,l,mid);
Query(cur|1,mid+1,r);
}
int main()
{
int i,j;b[0]=1;
for(i=1;i<=21;i++) b[i]=b[i-1]<<1;//初不初始化都可以,就是上面b[i]要变成1<<i
n=read();
for(i=1;i<=n;i++) a[i]=read();
built(1,1,n);
T=read();
while(T--)
{
if(read()==1)
{
L=read();R=read();ans=0;
Query(1,1,n);
printf("%lld\n",ans);
}
else
{
L=read();R=read();x=read();
for(i=0;i<21;i++)//判断x的第i位是不是1,并进行修改
if((x>>i)&1) Modify(1,1,n,i);
}
}
return 0;
}

最新文章

  1. runtime梳理。
  2. 自己动手写一个简单的MVC框架(第一版)
  3. Spring+MyBatis框架中sql语句的书写,数据集的传递以及多表关联查询
  4. poj 3613 经过k条边最短路 floyd+矩阵快速幂
  5. Navicat 连接 Oracle数据库 提示 cannot load OCI DLL 的解决
  6. 烂泥:通过vsphere给esxi添加本地硬盘
  7. CSS中 opacity的设置影响了index(层数)的改变
  8. soap的简单实现(PHP)
  9. 提高zxing生成二维码的容错率及zxing生成二维码的边框设置
  10. 浅谈C中的指针和数组(三)
  11. 搭建Ubuntu环境中的Error [dpkg 被中断,您必须手工运行 sudo dpkg --configure -a 解决此问题][安装Flashplayer出错 ]
  12. openStack 王者归来之 trivial matters
  13. tarjan算法(割点/割边/点连通分量/边连通分量/强连通分量)
  14. 学习笔记: JavaScript/JQuery 的cookie操作
  15. Python之路-操作系统&amp;网络基础
  16. ANDROID 中设计模式的采用--创建型模式
  17. openlayers 3方法继承
  18. 浅谈USB驱动架构 转载
  19. CAtia_打开提示:许可证过期怎么办
  20. Linux上Simplescalar/ARM的安装和运行文档

热门文章

  1. iOS开发那些事-响应内存警告
  2. uva 11754 Code Feat (中国剩余定理)
  3. uva 11806 Cheerleaders (容斥)
  4. springmvc 返回json数据给前台jsp页面展示
  5. linux中使用gbd进行单布调试
  6. [C#] 汉字转拼音,支持多音字
  7. HDU3336 Count the string 题解 KMP算法
  8. Linux查看用户及其权限管理
  9. Java JDBC学习实战(三): 事务管理
  10. 2019-10-30-C#-dotnet-core-局域网组播方法