• 【洛谷】【线段树+位运算】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
    ", 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 }
    光开关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
    ", Query(1, 1, n, x, y));
    62         else Update(1, 1, n, x, y);
    63     }
    64 }
    [TJOI2009]开关
  • 相关阅读:
    【洛谷】1852:[国家集训队]跳跳棋【LCA】【倍增?】
    【POJ】1835:宇航员【模拟】【三维行走】
    【BZOJ】3195: [Jxoi2012]奇怪的道路【状压/奇偶性】【思路】
    【10.24校内测试】【欧拉路径(有向+无向)】【双向链表/树状数组/线段树】
    【POJ】1840:Eqs【哈希表】
    【洛谷】4317:花神的数论题【数位DP】
    【POJ】1486:Sorting Slides【二分图关键边判定】
    算法模板
    Redis源码阅读一:简单动态字符串SDS
    总结下c/c++的一些调试经验
  • 原文地址:https://www.cnblogs.com/devilk-sjj/p/9056356.html
Copyright © 2020-2023  润新知