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. zoj 2006 Glass Beads

    Glass Beadshttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1006 Time Limit: 2 Seconds     ...

  2. iOS 网络请求--- AFNetworing的使用

    一.GET请求方式: //1.管理器 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; ...

  3. Sass 颜色函数

    /* * Sass 颜色函数 * RGB 颜色函数 * 1. rgb($red,$green,$blue):根据红.绿.蓝三个值创建一个颜色: * rgb(200,40,88) //根据r:200,g ...

  4. ssh无密码登录认证失败

    http://www.2cto.com/os/201401/271150.html https://unix.stackexchange.com/questions/36540/why-am-i-st ...

  5. 【bzoj3387-跨栏训练】线段树+dp

    我们可以想到一个dp方程:f[i][0]表示当前在i个栅栏的左端点,f[i][1]表示在右端点. 分两种情况: 第一种:假设现在要更新线段gh的左端点g,而它下来的路径被ef挡住了,那么必定是有ef来 ...

  6. MediaWiki安装配置(Linux)【转】

    转自:http://blog.csdn.net/gao36951/article/details/43965527 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 1Media ...

  7. HDU 6119 小小粉丝度度熊 双指针

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6119 题意:中文题面. 解法:先处理可能交叉的区间,然后容易发现满足双指针的特性. //HDU 611 ...

  8. 10 个打造 React.js App 的最佳 UI 框架

    10 个打造 React.js App 的最佳 UI 框架 在本文中,我们将分享一些助你打造 React.js App 最佳的 UI 框架.它们具备你所需要的基本 React 组件,以及易用的 API ...

  9. 关于IE8版本提示“不支持‘trim’此属性或者方法”的解决办法。转摘雨网络

    在js文件的前面加 String.prototype.trim = function () { return Trim(this); }; function LTrim(str) { var i; f ...

  10. vue css动画

    .toggle-cart-enter-active, .toggle-cart-leave-active { transition: all .3s ease-out; } .toggle-cart- ...