• 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]的伤害

    输出格式:

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

    输入输出样例

    输入样例#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
    

    说明

    样例解释:

    1011101001

    1100101001

    询问[1,5]输出3

    1111010001

    询问[1,10]输出6

    0000010001

    询问[2,6]输出1

    数据范围:

    10%数据2≤n,m≤10

    另有30%数据2≤n,m≤2000

    100%数据2≤n,m≤2*10^5

    By:worcher

    /*将lazy数组改一下,标志取反。*/
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #define lson root<<1,l,mid
    #define rson root<<1|1,mid+1,r
    #define N 200005
    using namespace std;
    string a;
    int n,m,p,l,r;
    int num[N],tree[N<<2],lazy[N<<2];
    void push(int root)
    {
        tree[root]=tree[root<<1]+tree[root<<1|1];
    }
    void pushdown(int root,int len)
    {
        if(lazy[root])
        {
            lazy[root<<1]^=1;    //标志以当节点为根的子树要取反 
            lazy[root<<1|1]^=1;
            tree[root<<1]=(len-(len>>1))-tree[root<<1];        //异或,将原先状态全部翻转
            tree[root<<1|1]=(len>>1)-tree[root<<1|1];    //该区间一共(r-l+1)>>1 个元素,减去自己即为异或后状态 
            lazy[root]=0;
        }
    }
    void build(int root,int l,int r)
    {
        if(l==r)    //找到叶子节点 
        {
            scanf("%1d",&tree[root]);    //%1d,只输入一个数字 
            return;
        }
        int mid=(l+r)>>1;
        build(lson);    //建左子树 
        build(rson);    //建右子树 
        push(root);
    }
    int query(int root,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R) return tree[root];    //查询区间包含当前区间,直接返回当前区间的值 
        pushdown(root,r-l+1);    //将lazy数组下放,更新子树节点 
        int mid=(l+r)>>1;
        int sum=0;
        if(L<=mid) sum+=query(lson,L,R);    //查询左子树 
        if(mid<R) sum+=query(rson,L,R);        //查询右子树 
        return sum;
    }
    void update(int root,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R)
        {
            lazy[root]^=1;    //表示以当前节点为根的子树要取反 
            tree[root]=r-l+1-tree[root];    //将当前子树中的值全部异或,总数减去当前数即为异或后的值 
            return;
        }
        pushdown(root,r-l+1);    //更新子树 
        int mid=(l+r)>>1;
        if(L<=mid) update(lson,L,R);    //更新左子树 
        if(mid<R) update(rson,L,R);        //更新右子树 
        push(root);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&p,&l,&r);
            if(p==0)
            {
                update(1,1,n,l,r);
            }
            else
            {
                printf("%d
    ",query(1,1,n,l,r));
            }
        }
        return 0;
    }
  • 相关阅读:
    《1024伐木累》-te别篇,庭审你知道吗?
    《1024伐木累》-人生最高境界,长的好看
    《1024伐木累》-买车,见梦中之人
    《1024伐木累》-小白篇之谈判-总章节七
    《1024伐木累》-新年到了,祝大家新年快乐!
    《1024伐木累》-年会了,剪刀石头布决胜
    《1024伐木累》-小白篇之丽jie(结束篇)-总章节六
    《1024伐木累》-老板,我又说实话了
    《1024伐木累》-BUG的通用解决办法
    [复习资料][随想]如何枚举一个排列
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8717416.html
Copyright © 2020-2023  润新知