【题目描述:】

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

2.  P3870 [TJOI2009]开关

 //[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的艺术的更多相关文章

  1. poj 3225 线段树+位运算

    略复杂的一道题,首先要处理开闭区间问题,扩大两倍即可,注意输入最后要\n,初始化不能随便memset 采用线段树,对线段区间进行0,1标记表示该区间是否包含在s内U T S ← S ∪ T 即将[l, ...

  2. hdu 5023 线段树+位运算

    主要考线段树的区间修改和区间查询,这里有一个问题就是这么把一个区间的多种颜色上传给父亲甚至祖先节点,在这里题目告诉我们最多30颜色,那么我们可以把这30中颜色用二进制储存和传给祖先节点,二进制的每一位 ...

  3. poj 2777 Count Color - 线段树 - 位运算优化

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 42472   Accepted: 12850 Description Cho ...

  4. Codeforces 620E New Year Tree(线段树+位运算)

    题目链接 New Year Tree 考虑到$ck <= 60$,那么用位运算统计颜色种数 对于每个点,重新标号并算出他对应的进和出的时间,然后区间更新+查询. 用线段树来维护. #includ ...

  5. 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 ...

  6. Count Color(线段树+位运算 POJ2777)

    Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 39917 Accepted: 12037 Descrip ...

  7. POJ 2777 Count Color(线段树+位运算)

    题目链接:http://poj.org/problem?id=2777 Description Chosen Problem Solving and Program design as an opti ...

  8. poj_2777线段树+位运算

    第一次没想到用位运算,不出意料的T了,,, PS:在床上呆了接近两个月后,我胡汉三又杀回来刷题啦-- #include<iostream> #include<cstdio> # ...

  9. [poj2777] Count Color (线段树 + 位运算) (水题)

    发现自己越来越傻逼了.一道傻逼题搞了一晚上一直超时,凭啥子就我不能过??? 然后发现cin没关stdio同步... Description Chosen Problem Solving and Pro ...

随机推荐

  1. 2 duplicate symbols for architecture“文件冲突”

      我在配置第三方库拷贝示例文件中的库文件到新项目完成相关配置之后报下面的错误:   错误的原因是在解决问题之后发现的(第三方库的项目示例demo中的 要拷贝到自己项目中的库  并不需要全部添加到自己 ...

  2. AVFoundation-视频录制以及拍照

    一般如果UI和UE在设计时只要求功能,对相机界面没什么要求的话,个人觉得调用系统相机(UIImagePickerController)就可以满足我们的需求比如照相或者录制视频,但是考虑界面美观性,有时 ...

  3. git 查看和撤销

    linux下文本的新建和追加内容 git cat-file -p ID可查看当前master的数据 观察Git 內部如何储存Commit 随便便抓一個 Commit 的 SHA1 开始: git ca ...

  4. java并发编程的艺术(一)---锁的基本属性

    本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...

  5. 从api接口获取数据-okhttp

    首先先介绍下api接口: API:应用程序接口(API:Application Program Interface) 通常用于数据连接,调用函数提供功能等等... 从api接口获取数据有四种方式:Ht ...

  6. javascript面向对象的常见写法与优缺点

    我们通过表单验证的功能,来逐步演进面向对象的方式.   对于刚刚接触javascript的朋友来说,如果要写一个验证用户名,密码,邮箱的功能, 一般可能会这么写: //表单验证 var checkUs ...

  7. CSS关于文本渲染的属性text-rendering

    CSS关于文本渲染的属性text-rendering告诉渲染引擎工作时如何优化显示文本. 浏览器会在渲染速度.易读性(清晰度)和几何精度方面做一个权衡. 我们知道,SVG-可缩放矢量图形(Scalab ...

  8. js-数组中查找特定元素并返回所有该元素的索引

    //在数组中查找所有出现的x,并返回一个包含匹配索引的数组 function findall(a,x){ var results=[], len=a.length, pos=0; while(pos& ...

  9. vue自定义日历组件的实现

    实现一个日期组件,如图: components.js代码如下: Vue.component('sc-calendar',{ template:'<div class="scCalend ...

  10. Django基础六之ORM中的锁和事务

    一 锁 行级锁 select_for_update(nowait=False, skip_locked=False) #注意必须用在事务里面,至于如何开启事务,我们看下面的事务一节. 返回一个锁住行直 ...