• 洛谷P2574 XOR的艺术(线段树)——Chemist


    当线段树遇上无敌位运算!

    还是老套路,线段树维护区间和,一个区间有几个"1"就是这个区间的区间和,同时支持区间修改区间查询,只不过操作从加法变成了异或。主要难点就在更新懒标记那里,详解见代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXX=200010;
    int read()
    {
        int ans=0;
        char ch=getchar(),last=' ';
        while(ch>'9'||ch<'0')
        {last=ch;ch=getchar();}
        while(ch>='0'&&ch<='9')
        {ans=ans*10+ch-'0';ch=getchar();}
        if(last=='-')ans=-ans;
        return ans;
    }
    int n,m,a[MAXX];
    char c[MAXX];
    struct Segment_Tree{
        int l,r,sum,tag;
    }t[4*MAXX];
    void pushup(int p)
    {
        t[p].sum=t[p*2].sum+t[p*2+1].sum;
        //维护区间和,也就是统计区间里有几个"1"
    }
    void pushdown(int p)//下放懒标记
    {
        if(t[p].tag){
            t[p*2].tag^=1;
            t[p*2+1].tag^=1;
            //更新子节点的懒标记
            t[p*2].sum=(t[p*2].r-t[p*2].l+1)-t[p*2].sum;
            //该区间异或1后全部取反,因此"1"的数量等于整个区间长减去原来"1"的数量
            t[p*2+1].sum=(t[p*2+1].r-t[p*2+1].l+1)-t[p*2+1].sum;
            t[p].tag=0;
        }
    }
    void build(int p,int l,int r)
    {
        t[p].l=l;t[p].r=r;
        if(l==r){t[p].sum=a[l];t[p].tag=0;return;}
        int mid=(l+r)/2;
        build(p*2,l,mid);
        build(p*2+1,mid+1,r);
        pushup(p);
    }
    void Xor(int p,int l,int r)
    {
        if(l<=t[p].l&&r>=t[p].r)
        {t[p].sum=(t[p].r-t[p].l+1)-t[p].sum;
        t[p].tag^=1;return;}
        pushdown(p);
        int mid=(t[p].l+t[p].r)/2;
        if(l<=mid)Xor(p*2,l,r);
        if(r>mid)Xor(p*2+1,l,r);
        pushup(p);
    }
    int ask(int p,int l,int r)
    {
        if(l<=t[p].l&&r>=t[p].r)return t[p].sum;
        pushdown(p);
        int mid=(t[p].l+t[p].r)/2;
        int ans=0;
        if(l<=mid)ans+=ask(p*2,l,r);
        if(r>mid)ans+=ask(p*2+1,l,r);
        return ans;
    }
    int main()
    {
        n=read();m=read();
        cin>>c+1;
        for(int i=1;i<=n;i++) 
         a[i]=c[i]-'0';
        build(1,1,n);
        for(int i=1;i<=m;i++){
            int op,l,r;
            op=read();l=read();r=read();
            if(op==0)Xor(1,l,r);
            else printf("%d
    ",ask(1,l,r));
        }
        return 0;
    }
  • 相关阅读:
    html的基本框架和常用标签
    防火墙
    Zenmap
    每日一招:熟练掌握变盘方向
    每日一招:赚钱最快的选股策略
    操盘策略:黄金做单时间
    每日一招:坚守六大方式选出优质股
    如何保卫你的牛市胜利果实?
    名家看后市:长阴破位不必慌
    每日一招:补仓需遵守的技巧
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9374039.html
Copyright © 2020-2023  润新知