【洛谷】【线段树+位运算】P2574 XOR的艺术
【题目描述:】
AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏。在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下
1、 拥有一个伤害串为长度为n的01串。
2、 给定一个范围[l,r],伤害为伤害串的这个范围内中1的个数
3、 会被随机修改伤害串中的数值,修改的方法是把[l,r]中的所有数xor上1
AKN想知道一些时刻的伤害,请你帮助他求出这个伤害
【输入格式:】
第一行两个数n,m,表示长度为n的01串,有m个时刻
第二行一个长度为n的01串,为初始伤害串
第三行开始m行,每行三个数p,l,r
若p为0,则表示当前时刻改变[l,r]的伤害串,改变规则如上
若p为1,则表示当前时刻AKN想知道[l,r]的伤害
【输出格式:】
对于每次询问伤害,输出一个数值伤害,每次询问输出一行
输入样例#: 输出样例#:
输入输出样例
【算法分析:】
对于xor 1运算,其实是把序列中的所有0变成1,把所有1变成0
所以一个区间xor 1之后的值就变成了"区间长度减去区间和"
而关于lazy-tag的修改也有一些需要注意的地方:
对于一个二进制数num,num ^ 1 ^ 1 = num
所以lazy-tag每次修改的时候需要xor 1:两次xor操作正好相互抵消,而不能单纯地把它变成1
【代码:】
//P2574 XOR的艺术
#include<iostream>
#include<cstdio>
using namespace std; const int MAXN = 2e5 + ; int n, m, a[MAXN];
struct Segment {
int sum;
bool tag;
}t[MAXN << ]; void Build(int o, int l, int r) {
if(l == r) t[o].sum = a[l];
else {
int mid = (l + r) >> ;
Build(o << , l, mid);
Build(o << |, mid + , r);
t[o].sum = t[o << ].sum + t[o << |].sum;
}
} inline void down(int o, int len) {
if(!t[o].tag) return;
t[o << ].sum = (len - (len >> )) - t[o << ].sum;
t[o << |].sum = (len >> ) - t[o << |].sum;
t[o << ].tag ^= ;
t[o << |].tag ^= ;
t[o].tag = ;
} int Query(int o, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) return t[o].sum;
down(o, r - l + );
int mid = (l + r) >> ;
int ret = ;
if(ql <= mid) ret += Query(o << , l, mid, ql, qr);
if(qr > mid) ret += Query(o << |, mid + , r, ql, qr);
return ret;
} void Update(int o, int l, int r, int ul, int ur) {
if(ul <= l && r <= ur) {
t[o].sum = r - l + - t[o].sum;
t[o].tag ^= ;
}
else {
down(o, r - l + );
int mid = (l + r) >> ;
if(ul <= mid) Update(o << , l, mid, ul, ur);
if(ur > mid) Update(o << |, mid + , r, ul, ur);
t[o].sum = t[o << ].sum + t[o << |].sum;
}
} int main() {
scanf("%d%d", &n, &m);
for(int i=; i<=n; ++i)
scanf("%1d", &a[i]);
Build(, , n);
while(m--) {
int fl, x, y;
scanf("%d%d%d", &fl, &x, &y);
if(!fl) Update(, , n, x, y);
else printf("%d\n", Query(, , n, x, y));
}
}
【 配套双倍经验题:】
1. P2846 [USACO08NOV]光开关Light Switching
#include<iostream>
#include<cstdio>
using namespace std; const int MAXN = 1e5 + ; int n, m;
struct Segment {
int sum;
bool tag;
}t[MAXN << ]; inline long long read() {
long long x = , f = ; char ch = getchar();
while(ch < '' || ch > '') {
if(ch == '-') f = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
x = (x << ) + (x << ) + ch - , ch = getchar();
return x * f;
} void Build(int o, int l, int r) {
if(l == r) t[o].sum = ;
else {
int mid = (l + r) >> ;
Build(o << , l, mid);
Build(o << |, mid + , r);
t[o].sum = t[o << ].sum + t[o << |].sum;
}
} inline void down(int o, int len) {
if(!t[o].tag) return;
t[o << ].sum = (len - (len >> )) - t[o << ].sum;
t[o << |].sum = (len >> ) - t[o << |].sum;
t[o << ].tag ^= ;
t[o << |].tag ^= ;
t[o].tag = ;
} void Update(int o, int l, int r, int ul, int ur) {
if(ul <= l && r <= ur) {
t[o].sum = r - l + - t[o].sum;
t[o].tag ^= ;
}
else {
down(o, r - l + );
int mid = (l + r) >> ;
if(ul <= mid) Update(o << , l, mid, ul, ur);
if(ur > mid) Update(o << |, mid + , r, ul, ur);
t[o].sum = t[o << ].sum + t[o << |].sum;
}
} int Query(int o, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) return t[o].sum;
down(o, r - l + );
int mid = (l + r) >> ;
int ret = ;
if(ql <= mid) ret += Query(o << , l, mid, ql, qr);
if(qr > mid) ret += Query(o << |, mid + , r, ql, qr);
return ret;
} int main() {
n = read(), m = read();
Build(, , n);
while(m--) {
int fl = read(), x = read(), y = read();
if(fl) printf("%d\n", Query(, , n, x, y));
else Update(, , n, x, y);
}
}
光开关Light Switching
//[TJOI2009]开关
#include<iostream>
#include<cstdio>
using namespace std; const int MAXN = + ; int n, m; struct Segment {
int sum; bool tag;
}t[MAXN << ]; inline int read() {
int x=, f=; char ch=getchar();
while(ch<'' || ch>'') {
if(ch == '-') f = -;
ch = getchar();
}
while(ch>='' && ch<='')
x=(x<<) + (x<<) + ch-, ch = getchar();
return x * f;
} inline void down(int o, int len) {
if(!t[o].tag) return;
t[o << ].sum = (len - (len >> )) - t[o << ].sum;
t[o << |].sum = (len >> ) - t[o << |].sum;
t[o << ].tag ^= , t[o << |].tag ^= ;
t[o].tag = ;
} void Update(int o, int l, int r, int ul, int ur) {
if(ul <= l && r <= ur) {
t[o].sum = r - l + - t[o].sum;
t[o].tag ^= ;
}
else {
down(o, r - l + );
int mid = (l + r) >> ;
if(ul <= mid) Update(o << , l, mid, ul, ur);
if(ur > mid) Update(o << |, mid + , r, ul, ur);
t[o].sum = t[o << ].sum + t[o << |].sum;
}
} int Query(int o, int l, int r, int ql, int qr) {
if(ql <= l && r <= qr) return t[o].sum;
down(o, r - l + );
int mid = (l + r) >> ;
int ret = ;
if(ql <= mid) ret += Query(o << , l, mid, ql, qr);
if(qr > mid) ret += Query(o << |, mid + , r, ql, qr);
return ret;
} int main() {
n = read(), m = read();
while(m--) {
int fl = read(), x = read(), y = read();
if(fl) printf("%d\n", Query(, , n, x, y));
else Update(, , n, x, y);
}
}
[TJOI2009]开关
【洛谷】【线段树+位运算】P2574 XOR的艺术的更多相关文章
- poj 3225 线段树+位运算
略复杂的一道题,首先要处理开闭区间问题,扩大两倍即可,注意输入最后要\n,初始化不能随便memset 采用线段树,对线段区间进行0,1标记表示该区间是否包含在s内U T S ← S ∪ T 即将[l, ...
- hdu 5023 线段树+位运算
主要考线段树的区间修改和区间查询,这里有一个问题就是这么把一个区间的多种颜色上传给父亲甚至祖先节点,在这里题目告诉我们最多30颜色,那么我们可以把这30中颜色用二进制储存和传给祖先节点,二进制的每一位 ...
- poj 2777 Count Color - 线段树 - 位运算优化
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 42472 Accepted: 12850 Description Cho ...
- Codeforces 620E New Year Tree(线段树+位运算)
题目链接 New Year Tree 考虑到$ck <= 60$,那么用位运算统计颜色种数 对于每个点,重新标号并算出他对应的进和出的时间,然后区间更新+查询. 用线段树来维护. #includ ...
- Codeforces Round #590 (Div. 3) D. Distinct Characters Queries(线段树, 位运算)
链接: https://codeforces.com/contest/1234/problem/D 题意: You are given a string s consisting of lowerca ...
- Count Color(线段树+位运算 POJ2777)
Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 39917 Accepted: 12037 Descrip ...
- POJ 2777 Count Color(线段树+位运算)
题目链接:http://poj.org/problem?id=2777 Description Chosen Problem Solving and Program design as an opti ...
- poj_2777线段树+位运算
第一次没想到用位运算,不出意料的T了,,, PS:在床上呆了接近两个月后,我胡汉三又杀回来刷题啦-- #include<iostream> #include<cstdio> # ...
- [poj2777] Count Color (线段树 + 位运算) (水题)
发现自己越来越傻逼了.一道傻逼题搞了一晚上一直超时,凭啥子就我不能过??? 然后发现cin没关stdio同步... Description Chosen Problem Solving and Pro ...
随机推荐
- VMWare开启DHCP和NAT服务(VMWare无法通过NAT上网以及和host主机通信的问题解决)
最近在学习Hadoop,开始做一个集群.由于各个节点的IP地址需要保持不变,我决定在VMWare采用NAT的模式联网. 但是在安装Ubuntu系统的时候,提示我DHCP服务未开启. Your netw ...
- SpringCloud Eureka(注册中心集群)
多个注册中心,其实用不同的配置对应 不同的端口号注册就行了. 注册中心自己也是个服务,看看之前的单个注册中心是怎么样的呢? server: port: 8888 # 服务端口eureka: insta ...
- golang使用graphviz
graphviz的介绍请参考: http://www.cnblogs.com/ghj1976/p/4539788.html 安装 graphviz 需要在 http://www.graphviz.o ...
- MVC,MVP 和 MVVM 的图示(转)
作者: 阮一峰 日期: 2015年2月 1日 转自:http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html 复杂的软件必须有清晰合理的架构,否则 ...
- QT的信号和槽机制简介
信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工具以及在实际使用过程中应注意的一些问题. QT是一个跨平台的C++ GUI应用构架,它提供了丰富的窗口部 ...
- 数学建模三剑客MSN
前言 不管是不是巴萨的球迷,只要你喜欢足球,就一定听说过梅西(Messi).苏亚雷斯(Suarez)和内马尔(Neymar)这个MSN组合.在众多的数学建模辅助工具中,也有一个犀利无比的MSN组合,他 ...
- js中innerHTML和innerText的用法
<div id="test"> <span style="color:red">test1</span> test2 < ...
- 612.1.002 ALGS4 | Analysis of Algorithms
我们生活在大数的时代 培养数量级的敏感! Tip:见招拆招 作为工程师,你先要能实现出来. 充实基础,没有什么不好意思 哪怕不完美.但是有时候完成比完美更重要. 之后再去想优化 P.S.作者Rober ...
- 如何使用 adb 命令实现自动化测试
如何使用 adb 命令实现自动化测试 一.前提: 1.打开手机调试模式,确保手机已正常连接电脑,可在电脑上通过adb devices命令查看,结果如下说明连接成功: List of devices a ...
- Linux 启动脚本及chkconfig命令之自启动服务
有时我们会碰到这样的情况,系统启动的时候报一大堆无法连接mysql的错误,问题在mysql数据库还没有启动的时候已经启动了一些需要连接mysql数据库的服务.这样我们就得修改启动顺序,把需要连接mys ...