Description

给定一个长为\(n(n<=10^5)\)的数组

数组里的数不超过\(10^6\)

有两种操作:

1:求\(sum[l,r]\);

2:对\([l,r]\)中的所有数和\(x\)异或

Input

第一行一个整数\(n\),代表有一个长度为\(n\)的数组。

第二行\(n\)个整数,代表\(a_i\)

第三行为一个整数\(m\),代表有\(m\)次操作。

接下来\(m\)行每行描述一个操作。

Output

对于每一个操作\(1\),输出一行代表\(sum[l,r]\).

这题不错,线段树+二进制拆位

由于异或不具有叠加性,所以不能用\(lazy\)标记直接异或。

我们记录\(tr[o][i]\)代表当前节点\(o\),二进制位\(i\)上是\(1\)的数有多少个。

由于,如果某一二进制位上原来为\(1\),且当前异或的数\(x\),当前二进制位上也有\(1\),那么我们的当前\(tr[o][i]=r-l+1-tr[o][i]\)。

可以理解为\(01\)交换。

然后由于\(2^{20}\)比\(10^6\)要大。

所以只需要拆到\(20\)即可。

然后直接计算即可。

PS:记得开\(long \ long\)!

代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#define int long long
#define R register using namespace std; const int gz=1e5+8; inline void in(R int &x)
{
R int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
} int n,tr[gz<<2][21],tg[gz<<2],m; #define ls o<<1
#define rs o<<1|1 inline void up(R int o)
{
for(R int i=20;~i;i--)
tr[o][i]=tr[ls][i]+tr[rs][i];
} void build(R int o,R int l,R int r)
{
if(l==r)
{
R int x;in(x);
for(R int i=20;~i;i--)
if((x>>i)&1)tr[o][i]++;
return;
}
R int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
up(o);
} inline void down(R int o,R int l,R int r)
{
if(tg[o]==0)return;
tg[ls]^=tg[o];tg[rs]^=tg[o];
R int mid=(l+r)>>1;
for(R int i=20;~i;i--)
{
if((tg[o]>>i)&1)
tr[ls][i]=mid-l+1-tr[ls][i],
tr[rs][i]=r-mid-tr[rs][i];
}
tg[o]=0;
return;
} void change(R int o,R int l,R int r,R int x,R int y,R int k)
{
if(x<=l and y>=r)
{
tg[o]^=k;
for(R int i=20;~i;i--)
if((k>>i)&1)
tr[o][i]=r-l+1-tr[o][i];
return;
}
down(o,l,r);
int mid=(l+r)>>1;
if(x<=mid)change(ls,l,mid,x,y,k);
if(y>mid) change(rs,mid+1,r,x,y,k);
up(o);
} int query(R int o,R int l,R int r,R int x,R int y)
{
if(x<=l and y>=r)
{
R int res=0;
for(R int i=20;~i;i--)
res+=(1<<i)*tr[o][i];
return res;
}
down(o,l,r);
R int mid=(l+r)>>1,as=0;
if(x<=mid)as+=query(ls,l,mid,x,y);
if(y>mid)as+=query(rs,mid+1,r,x,y);
return as;
} signed main()
{
in(n);build(1,1,n);in(m);
for(R int opt,l,r,x;m;m--)
{
in(opt);
if(opt==1)
{
in(l),in(r);
printf("%lld\n",query(1,1,n,l,r));
}
else
{
in(l),in(r),in(x);
change(1,1,n,l,r,x);
}
}
}

最新文章

  1. C,C++,Lisp,Java,Perl,Python
  2. Ubuntu配置LAMP+MediaWiki及常见问题
  3. Everyday is an Opportunity
  4. jquery用ajax方式从后台获取json数据,将内容填充到下拉列表。
  5. ios开发--tcp/ip
  6. 删除 mysql (rpm)
  7. PHP对URL设置
  8. javascript延迟加载及异步(defer和async)
  9. (原)前端知识杂烩(css系列)
  10. document.body的一些用法以及js中的常见问题
  11. openstack controller ha测试环境搭建记录(三)——配置haproxy
  12. js代码实现放大镜效果
  13. C语言程序设计第二次作业—————顺序结构
  14. Spring Cloud authentication with JWT service
  15. 常用CSS样式速查
  16. Oozie如何和安装部署
  17. SpringBoot--web版的ocr
  18. (17)线程队列---queue LifoQueue PriorityQueue
  19. Java 的NIO 3个主要概念 Channel、Buffer、Selector
  20. [LeetCode&amp;Python] Problem 453. Minimum Moves to Equal Array Elements

热门文章

  1. UVA 1262 Password
  2. Gradle编译时下载依赖失败解决方法
  3. Hadoop大数据生态系统及常用组件(山东数漫江湖)
  4. 【洛谷 P4320】 道路相遇 (圆方树,LCA)
  5. MSSQL数据库 &quot;无法删除数据库 &quot;***&quot;,因为该数据库当前正在使用&quot; 解决方案
  6. LCD 每隔10分钟 自动熄灭 --打开Framebuffer console的时候【转】
  7. 設定 gpio 為 讀取用途,需注意的參數
  8. Python的语言特性
  9. mybatis源码阅读(动态代理)
  10. [New learn]SDWebImage框架的基本使用