zoukankan      html  css  js  c++  java
  • 讲课专用——线段树——多标记问题

    题目链接: https://www.luogu.org/problemnew/show/P2572

    题解:

    覆盖标记会对取反标记有什么影响?   

    取反标记作废

    取反标记会对覆盖标记有什么影响?   

    若有覆盖标记,将覆盖标记取反,不打取反标记

    若无覆盖标记,打上取反标记

    所以一个节点只可能同时拥有一种标记,不需要考虑这两种标记同时下放的顺序问题

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 100001
    
    int siz[N<<2];
    int sum1[N<<2],sum0[N<<2];
    int mx1[N<<2],mx0[N<<2];
    int lcon1[N<<2],rcon1[N<<2],lcon0[N<<2],rcon0[N<<2];
    int f[N<<2];
    bool rev[N<<2];
    
    int la,ans;
    
    char s[21]; int ll;
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void up(int k)
    {
        int L=k<<1,R=k<<1|1;
        sum1[k]=sum1[L]+sum1[R];
        sum0[k]=sum0[L]+sum0[R];
        mx1[k]=max(mx1[L],mx1[R]);
        mx1[k]=max(mx1[k],rcon1[L]+lcon1[R]);
        mx0[k]=max(mx0[L],mx0[R]);
        mx0[k]=max(mx0[k],rcon0[L]+lcon0[R]);
        if(mx1[L]==siz[L]) lcon1[k]=siz[L]+lcon1[R];
        else lcon1[k]=lcon1[L];
        if(mx1[R]==siz[R]) rcon1[k]=siz[R]+rcon1[L];
        else rcon1[k]=rcon1[R];
        if(mx0[L]==siz[L]) lcon0[k]=siz[L]+lcon0[R];
        else lcon0[k]=lcon0[L];
        if(mx0[R]==siz[R]) rcon0[k]=siz[R]+rcon0[L];
        else rcon0[k]=rcon0[R]; 
    }
    
    void build(int k,int l,int r)
    {
        siz[k]=r-l+1;
        f[k]=-1;
        if(l==r) 
        {
            read(la);
            if(la) sum1[k]=mx1[k]=lcon1[k]=rcon1[k]=1;
            else sum0[k]=mx0[k]=lcon0[k]=rcon0[k]=1;
            return;
        }
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        up(k);
    }
    
    void down(int k)
    {
        int L=k<<1,R=k<<1|1;
        if(f[k]!=-1)
        {
            if(!f[k]) 
            {
                 sum0[L]=mx0[L]=lcon0[L]=rcon0[L]=siz[L];
                 sum1[L]=mx1[L]=lcon1[L]=rcon1[L]=0;
                 sum0[R]=mx0[R]=lcon0[R]=rcon0[R]=siz[R];
                 sum1[R]=mx1[R]=lcon1[R]=rcon1[R]=0; 
            }
            else
            {
                 sum0[L]=mx0[L]=lcon0[L]=rcon0[L]=0;
                 sum1[L]=mx1[L]=lcon1[L]=rcon1[L]=siz[L];
                 sum0[R]=mx0[R]=lcon0[R]=rcon0[R]=0;
                 sum1[R]=mx1[R]=lcon1[R]=rcon1[R]=siz[R]; 
            }
            rev[L]=rev[R]=false;
            f[L]=f[R]=f[k];
            f[k]=-1;
        }
        if(rev[k])
        {
            swap(sum0[L],sum1[L]);
            swap(mx0[L],mx1[L]);
            swap(lcon0[L],lcon1[L]);
            swap(rcon0[L],rcon1[L]); 
            if(f[L]!=-1) f[L]=!f[L];
            else rev[L]=!rev[L]; 
            swap(sum0[R],sum1[R]);
            swap(mx0[R],mx1[R]);
            swap(lcon0[R],lcon1[R]);
            swap(rcon0[R],rcon1[R]); 
            if(f[R]!=-1) f[R]=!f[R];
            else rev[R]=!rev[R]; 
            rev[k]=false;
        } 
    }
    
    void change(int k,int l,int r,int a,int b,int opt)
    {
        if(l>=a && r<=b)
        {
            if(!opt) 
            {
                sum0[k]=mx0[k]=lcon0[k]=rcon0[k]=siz[k];
                sum1[k]=mx1[k]=lcon1[k]=rcon1[k]=0;
            }
            else 
            {
                sum1[k]=mx1[k]=lcon1[k]=rcon1[k]=siz[k];
                sum0[k]=mx0[k]=lcon0[k]=rcon0[k]=0;
            } 
            f[k]=opt;
            rev[k]=false;
            return;
        }
        down(k);
        int mid=l+r>>1;
        if(a<=mid) change(k<<1,l,mid,a,b,opt);
        if(b>mid) change(k<<1|1,mid+1,r,a,b,opt);
        up(k); 
    }
    
    void reversal(int k,int l,int r,int a,int b)
    {
        if(l>=a && r<=b)
        {
            swap(sum0[k],sum1[k]);
            swap(mx0[k],mx1[k]);
            swap(lcon0[k],lcon1[k]);
            swap(rcon0[k],rcon1[k]); 
            if(f[k]!=-1) f[k]=!f[k];
            else rev[k]=!rev[k]; 
            return;
        }
        down(k);
        int mid=l+r>>1;
        if(a<=mid) reversal(k<<1,l,mid,a,b);
        if(b>mid) reversal(k<<1|1,mid+1,r,a,b);
        up(k);
    }
    
    void query_sum(int k,int l,int r,int a,int b)
    {
        if(l>=a && r<=b) 
        {
            ans+=sum1[k];
            return;
        }
        down(k);
        int mid=l+r>>1;
        if(a<=mid) query_sum(k<<1,l,mid,a,b);
        if(b>mid) query_sum(k<<1|1,mid+1,r,a,b);
    } 
    
    void query_mx(int k,int l,int r,int a,int b,int &mx,int &mxl,int &mxr)
    {
        if(l>=a && r<=b)
        {
             mx=mx1[k];
             mxl=lcon1[k];
             mxr=rcon1[k];
             return;
        }
        down(k);
        int mid=l+r>>1;
        int Lmx=0,Rmx=0,Lmxl=0,Rmxl=0,Lmxr=0,Rmxr=0;
        if(a<=mid) query_mx(k<<1,l,mid,a,b,Lmx,Lmxl,Lmxr);
        if(b>mid) query_mx(k<<1|1,mid+1,r,a,b,Rmx,Rmxl,Rmxr);
        mx=max(Lmx,Rmx);
        mx=max(Lmxr+Rmxl,mx);
        if(Lmxl==siz[k<<1]) mxl=Lmxl+Rmxl;
        else mxl=Lmxl;
        if(Rmxr==siz[k<<1|1]) mxr=Rmxr+Lmxr;
        else mxr=Rmxr;
    } 
    
    void out(int x)
    {
        do s[++ll]=x%10+'0'; while(x/=10);
        while(ll) putchar(s[ll--]);
        putchar('
    ');
    }
    
    void init()
    {
        int n,m;
        read(n); read(m);
        build(1,1,n);
        int opt,a,b;
        int mx,mxl,mxr;
        while(m--)
        {
            read(opt); read(a); read(b);
            ++a; ++b;
            if(opt==0 || opt==1) change(1,1,n,a,b,opt); 
            else if(opt==2) reversal(1,1,n,a,b);
            else if(opt==3) 
            {
                ans=0;
                query_sum(1,1,n,a,b);
                out(ans);
            }
            else
            {
                query_mx(1,1,n,a,b,mx,mxl,mxr);
                out(mx);
            }
        }
    }
    
    int main()
    {
        init();
        return 0;
    } 
  • 相关阅读:
    学习工具
    Qt 之 QApplication
    Qt中常用的类
    关于在Qt里让程序休眠一段时间的方法总结
    Qt setWindow setViewPort
    ajax回调数据 Structs has detected an unhandled exception 问题
    Struts2配置拦截器自定义栈时抛异常:Unable to load configuration.
    es6之map解构数组去重
    ES6之对象的方法
    ES6之genorator和yield使用(迭代器)
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/11142877.html
Copyright © 2011-2022 走看看