【洛谷】【线段树+位运算】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 }

 

【 配套双倍经验题:】

1.  P2846 [USACO08NOV]光开关Light Switching

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 const int MAXN = 1e5 + 1;
 6 
 7 int n, m;
 8 struct Segment {
 9     int sum;
10     bool tag;
11 }t[MAXN << 2];
12 
13 inline long long read() {
14     long long x = 0, f = 1; char ch = getchar();
15     while(ch < '0' || ch > '9') {
16         if(ch == '-') f = -1;
17         ch = getchar();
18     }
19     while(ch >= '0' && ch <= '9')
20         x = (x << 3) + (x << 1) + ch - 48, ch = getchar();
21     return x * f;
22 }
23 
24 void Build(int o, int l, int r) {
25     if(l == r) t[o].sum = 0;
26     else {
27         int mid = (l + r) >> 1;
28         Build(o << 1, l, mid);
29         Build(o << 1|1, mid + 1, r);
30         t[o].sum = t[o << 1].sum + t[o << 1|1].sum;
31     }
32 }
33 
34 inline void down(int o, int len) {
35     if(!t[o].tag) return;
36     t[o << 1].sum = (len - (len >> 1)) - t[o << 1].sum;
37     t[o << 1|1].sum = (len >> 1) - t[o << 1|1].sum;
38     t[o << 1].tag ^= 1;
39     t[o << 1|1].tag ^= 1;
40     t[o].tag = 0;
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 Query(int o, int l, int r, int ql, int qr) {
58     if(ql <= l && r <= qr) return t[o].sum;
59     down(o, r - l + 1);
60     int mid = (l + r) >> 1;
61     int ret = 0;
62     if(ql <= mid) ret += Query(o << 1, l, mid, ql, qr);
63     if(qr > mid) ret += Query(o << 1|1, mid + 1, r, ql, qr);
64     return ret;
65 }
66 
67 int main() {
68     n = read(), m = read();
69     Build(1, 1, n);
70     while(m--) {
71         int fl = read(), x = read(), y = read();
72         if(fl) printf("%d\n", Query(1, 1, n, x, y));
73         else Update(1, 1, n, x, y);
74     }
75 }
光开关Light Switching

 

2.  P3870 [TJOI2009]开关

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

 

posted @ 2018-05-18 15:18  DEVILK  阅读(248)  评论(0编辑  收藏  举报