【题目描述:】
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]的伤害
【输出格式:】
对于每次询问伤害,输出一个数值伤害,每次询问输出一行
输入样例#1: 10 6 1011101001 0 2 4 1 1 5 0 3 7 1 1 10 0 1 4 1 2 6 输出样例#1: 3 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 ", 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 ", Query(1, 1, n, x, y)); 73 else Update(1, 1, n, x, y); 74 } 75 }
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 ", Query(1, 1, n, x, y)); 62 else Update(1, 1, n, x, y); 63 } 64 }