【洛谷】【线段树+位运算】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]的伤害

【输出格式:】

对于每次询问伤害,输出一个数值伤害,每次询问输出一行

输入样例#110 6
1011101001
0 2 4
1 1 5
0 3 7
1 1 10
0 1 4
1 2 6
输出样例#13
6
1
输入输出样例

【算法分析:】

对于xor 1运算,其实是把序列中的所有0变成1,把所有1变成0

所以一个区间xor 1之后的值就变成了"区间长度减去区间和"

而关于lazy-tag的修改也有一些需要注意的地方:

  对于一个二进制数num,num ^ 1 ^ 1 = num

  所以lazy-tag每次修改的时候需要xor 1:两次xor操作正好相互抵消,而不能单纯地把它变成1

【代码:】

 1 //P2574 XOR的艺术
 2 #include<iostream>
 3 #include<cstdio>
 4 using namespace std;
 5 
 6 const int MAXN = 2e5 + 1;
 7 
 8 int n, m, a[MAXN];
 9 struct Segment {
10     int sum;
11     bool tag;
12 }t[MAXN << 2];
13 
14 void Build(int o, int l, int r) {
15     if(l == r) t[o].sum = a[l];
16     else {
17         int mid = (l + r) >> 1;
18         Build(o << 1, l, mid);
19         Build(o << 1|1, mid + 1, r);
20         t[o].sum = t[o << 1].sum + t[o << 1|1].sum;
21     }
22 }
23 
24 inline void down(int o, int len) {
25     if(!t[o].tag) return;
26     t[o << 1].sum = (len - (len >> 1)) - t[o << 1].sum;
27     t[o << 1|1].sum = (len >> 1) - t[o << 1|1].sum;
28     t[o << 1].tag ^= 1;
29     t[o << 1|1].tag ^= 1;
30     t[o].tag = 0;
31 }
32 
33 int Query(int o, int l, int r, int ql, int qr) {
34     if(ql <= l && r <= qr) return t[o].sum;
35     down(o, r - l + 1);
36     int mid = (l + r) >> 1;
37     int ret = 0;
38     if(ql <= mid) ret += Query(o << 1, l, mid, ql, qr);
39     if(qr > mid) ret += Query(o << 1|1, mid + 1, r, ql, qr);
40     return ret;
41 }
42 
43 void Update(int o, int l, int r, int ul, int ur) {
44     if(ul <= l && r <= ur) {
45         t[o].sum = r - l + 1 - t[o].sum;
46         t[o].tag ^= 1;
47     }
48     else {
49         down(o, r - l + 1);
50         int mid = (l + r) >> 1;
51         if(ul <= mid) Update(o << 1, l, mid, ul, ur);
52         if(ur > mid) Update(o << 1|1, mid + 1, r, ul, ur);
53         t[o].sum = t[o << 1].sum + t[o << 1|1].sum;
54     }
55 }
56 
57 int main() {
58     scanf("%d%d", &n, &m);
59     for(int i=1; i<=n; ++i)
60         scanf("%1d", &a[i]);
61     Build(1, 1, n);
62     while(m--) {
63         int fl, x, y;
64         scanf("%d%d%d", &fl, &x, &y);
65         if(!fl) Update(1, 1, n, x, y);
66         else printf("%d\n", Query(1, 1, n, x, y));
67     }
68 }

猜你喜欢

转载自www.cnblogs.com/devilk-sjj/p/9056356.html