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);
}
}
}

线段树+二进制位拆分【CF242E】XOR on Segment的更多相关文章

  1. CF242E XOR on Segment

    CF242E XOR on Segment codeforces 洛谷 关于异或,无法运用懒标记实现区间异或: 可以像trie树一样拆位,将每个值拆成二进制数,对此建相应个数的线段树. 0 1与 0异 ...

  2. 线段树+离散化 IP地址段检查 SEGMENT TREE

    Problem: Give a series of IP segments, for example, [0.0.0.1-0.0.0.3], [123.234.232.21-123.245.21.1] ...

  3. CodeForces 242E "XOR on Segment"(线段树)

    传送门 •题意 给你一个包含 n 个数的序列 a,定义序列上的两个操作: (1)$1,l,r\ :\ ans=\sum_{i=l}^{r}a_i$; (2)$2,l,r,x\ :\ \forall\ ...

  4. codeforces 22E XOR on Segment 线段树

    题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...

  5. Codeforces 242E:XOR on Segment(位上的线段树)

    http://codeforces.com/problemset/problem/242/E 题意:给出初始n个数,还有m个操作,操作一种是区间求和,一种是区间xor x. 思路:昨天比赛出的一道类似 ...

  6. codeforces 242E - XOR on Segment (线段树 按位数建树)

    E. XOR on Segment time limit per test 4 seconds memory limit per test 256 megabytes input standard i ...

  7. Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)

    题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题 ...

  8. CodeForces 242E - XOR on Segment 二维线段树?

    今天练习赛的题....又是线段树的变换..拿到题我就敲了个点更新区间查询的..果断超时...然后想到了可以将每个数与合表示成不进位的二进制数..这样就可以区间进行更新了..比赛的时候写搓了..刚重写了 ...

  9. codeforces 242E. XOR on Segment 线段树

    题目链接 给n个数, 两种操作, 一种是求区间内的数的和, 一种是将区间内的数异或x. 异或x没有什么思路, 单个异或肯定超时, 区间异或也没有办法做....后来才知道可以按位建线段树, 这样建20棵 ...

随机推荐

  1. 【C++ STL】Stack

    1.定义 class stack<> 实作出一个stack(也成为LIFO,后进先出),你可以使用push()将任意数量的元素置入stack中,也可以使用pop()将元素依次插入次序反序从 ...

  2. webpack自动化构建你的项目

    1.读万卷书,行万里路. 2.书山有路勤为径,学海无涯苦作舟. 技术段: 相信很多刚接触前端的小伙伴,对一些自动化工具会感觉无可下手.现在前端的发展的势头,势必和后台形成一个对立面,独挡一面. 这篇文 ...

  3. ImageView设置边框 以及内部图片居中显示 在AndroidStudio中添加shape.xml文件

    效果如图 边框设置:shape文件 <shape xmlns:android="http://schemas.android.com/apk/res/android"> ...

  4. python 异步IO( asyncio) 协程

    python asyncio 网络模型有很多中,为了实现高并发也有很多方案,多线程,多进程.无论多线程和多进程,IO的调度更多取决于系统,而协程的方式,调度来自用户,用户可以在函数中yield一个状态 ...

  5. 用selenium 模块控制浏览器

    11.8 用selenium 模块控制浏览器selenium 模块让Python 直接控制浏览器,实际点击链接,填写登录信息,几乎就像是有一个人类用户在与页面交互.与Requests 和Beautif ...

  6. HDU 6188 Duizi and Shunzi 贪心

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6188 题意:给了n个数,然后现在问我们最多构成多少个对子和顺子,其中对子是2个相同的牌,顺子是3个连续 ...

  7. C高级 跨平台协程库

    1.0 协程库引言 协程对于上层语言还是比较常见的. 例如C# 中 yield retrun, lua 中 coroutine.yield 等来构建同步并发的程序. 本文就是探讨如何从底层实现开发级别 ...

  8. 微信小程序滚动条返回顶部

    scroll-view(可滚动视图区域): 使用竖向滚动时,需要给<scroll-view/>一个固定高度,通过 WXSS 设置 height,将scroll-y属性设置为true,将en ...

  9. seq和{ }生成序列

    基本用法 [root@C ~]# seq 5 1 2 3 4 5 [root@C ~]# echo {1..5} 1 2 3 4 5 #步进输出 [root@C ~]# seq 1 2 5 1 3 5 ...

  10. 实现atoi函数

    atoi函数最关键的地方是想好测试用例: 输入为空字符串,输出为0; 输入字符串大小超过INT_MAX输出INT_MAX; 输入字符串大小小于INT_MIN输出INT_MIN; 输入字符串中含有不规则 ...