线段树+二进制位拆分【CF242E】XOR on Segment
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的更多相关文章
- CF242E XOR on Segment
CF242E XOR on Segment codeforces 洛谷 关于异或,无法运用懒标记实现区间异或: 可以像trie树一样拆位,将每个值拆成二进制数,对此建相应个数的线段树. 0 1与 0异 ...
- 线段树+离散化 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] ...
- CodeForces 242E "XOR on Segment"(线段树)
传送门 •题意 给你一个包含 n 个数的序列 a,定义序列上的两个操作: (1)$1,l,r\ :\ ans=\sum_{i=l}^{r}a_i$; (2)$2,l,r,x\ :\ \forall\ ...
- codeforces 22E XOR on Segment 线段树
题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...
- Codeforces 242E:XOR on Segment(位上的线段树)
http://codeforces.com/problemset/problem/242/E 题意:给出初始n个数,还有m个操作,操作一种是区间求和,一种是区间xor x. 思路:昨天比赛出的一道类似 ...
- codeforces 242E - XOR on Segment (线段树 按位数建树)
E. XOR on Segment time limit per test 4 seconds memory limit per test 256 megabytes input standard i ...
- 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. 这题 ...
- CodeForces 242E - XOR on Segment 二维线段树?
今天练习赛的题....又是线段树的变换..拿到题我就敲了个点更新区间查询的..果断超时...然后想到了可以将每个数与合表示成不进位的二进制数..这样就可以区间进行更新了..比赛的时候写搓了..刚重写了 ...
- codeforces 242E. XOR on Segment 线段树
题目链接 给n个数, 两种操作, 一种是求区间内的数的和, 一种是将区间内的数异或x. 异或x没有什么思路, 单个异或肯定超时, 区间异或也没有办法做....后来才知道可以按位建线段树, 这样建20棵 ...
随机推荐
- LightOJ 1218 概率水题(几何分布)
题意:给你一个n面骰子,问你投出所有面需要的次数的期望值是多少. 题解:放在过去估计秒解,结果现在自己想好久,还查了下,有人用极限证明...实际上仔细想想这种情况投出与前面不一样的概率p的倒数就是次数 ...
- PACM Team(牛客第三场多校赛+dp+卡内存+打印路径)
题目链接(貌似未报名的不能进去):https://www.nowcoder.com/acm/contest/141/A 题目: 题意:背包题意,并打印路径. 思路:正常背包思路,不过五维的dp很容易爆 ...
- bzoj 1305 二分+最大流判定|贪心
首先我们二分一个答案mid,在判定是否能举办mid次,那么对于每个次我们可以用最大流根据是否满流(流量为n*mid)来判定,对于每个点我们拆成两个点,分别表示这个人要和他喜欢和不喜欢的人一起跳舞,那么 ...
- 获取天气api
http://wthrcdn.etouch.cn/WeatherApi?citykey=101010100通过城市id获得天气数据,xml文件数据,当错误时会有<error>节点http: ...
- 小程序_改变switch组件的大小
微信开发文档中,switch能修改颜色,没有直接修改switch大小的属性.用一般控件height & width来修改宽高是没有用的. 使用如下方法: 在.wxss文件: .wx-switc ...
- python开发第二十六天CMDB
概要: 1.采集资产 2.API 一.资产采集 1.采集方式的配置 2.插件的定制 3.测试模式 4.错误日志(必须是行级的详细错误信息) 5.汇报数据-->遵循资产的唯一性 (1)只针对物理机 ...
- 【Python学习】程序运行完发送邮件提醒
有时候我们运行一个需要跑很长时间的程序,不管是在云主机还是本地主机上运行,我们都不可能一直守在电脑面前等.所以想到使用邮件来通知提醒. 示例代码如下 # -*- coding: utf-8 -*- # ...
- CentOS7手动编译安装内核4.11.7
1. 进入/usr/src/目录 cd /usr/src 2. 下载内核源码,网址:https://www.kernel.org wget https://cdn.kernel.org/pub/lin ...
- Linux 入门记录:五、vi、vim 编辑器
一.vi.vim编辑器 vi 是一个命令行界面下的文本编辑工具,最早在 1976 年由 Bill Joy 开发.当时名字叫做 ex.vi 支持绝大多数操作系统(最早在类 Unix 操作系统的 BSD上 ...
- python基础===Windows环境下使用pip install 安装出错"Cannot unpack file"解决办法
不知道为什么,加了豆瓣镜像源还是不行 这个命令可以解决! pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douba ...