线段树——讲课用——多标记问题

题目链接: 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('\n');
}

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;
} 

 

posted @ 2019-07-06 15:27  TRTTG  阅读(264)  评论(0编辑  收藏  举报