1. 程式人生 > >【BZOJ4592】【Shoi2015】腦洞治療儀 線段樹

【BZOJ4592】【Shoi2015】腦洞治療儀 線段樹

第一眼看成了一個裸的01弱智線段樹,然後發現弱智的是自己。。。主要就是如果好腦洞不夠用了就儘量往前面補這一個操作。。。

其實還是不難。。。我們線上段樹遍歷的時候優先往前面補,如果這個區間不夠補就分別檢查兩個子區間,可以證明這樣的操作還是log級別的(反正我不會233),然後就是最長連續區間的套路辣

/**************************************************************
    Problem: 4592
    User: RicardoWang
    Language: C++
    Result: Accepted
    Time:13220 ms
    Memory:32528 kb
****************************************************************/
 
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
void _read(int &x)
{
    x=0; char ch=getchar(); bool flag=false;
    while(ch<'0' || ch>'9'){if(ch=='-')flag=true;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} if(flag)x=-x;return ;
}
#define MAXN 400005
struct data
{
    int L,R,Sum0,Sum1,lmax,rmax,max;
}w[MAXN*2];
int N,M,np,rt,chi[2*MAXN][2],down[MAXN*2];
void pushup(data &now,data lc,data rc)
{
    now=(data){lc.L,rc.R,lc.Sum0+rc.Sum0,lc.Sum1+rc.Sum1,lc.lmax,rc.rmax,max(lc.rmax+rc.lmax,max(lc.max,rc.max))};
    if(lc.Sum1==0)now.lmax+=rc.lmax;
    if(rc.Sum1==0)now.rmax+=lc.rmax;
    return ;
}
void add(data &x,int v)
{
    int L=x.L,R=x.R;
    if(v==0)
    {
        x=(data){L,R,R-L+1,0,R-L+1,R-L+1,R-L+1};
    }
    else
    {
        x=(data){L,R,0,R-L+1,0,0,0};
    }
    return ;
}
void pushdown(int now)
{
    if(down[now]>0)
    {
       // data &lc=w[chi[now][0]],&rc=w[chi[now][1]];
        if(down[now]==1)
        {
            add(w[chi[now][0]],0);//lc=(data){lc.L,lc.R,lc.R-lc.L+1,0,lc.R-lc.L+1,lc.R-lc.L+1,lc.R-lc.L+1};
            add(w[chi[now][1]],0);//rc=(data){rc.L,rc.R,rc.R-rc.L+1,0,rc.R-rc.L+1,rc.R-rc.L+1,rc.R-rc.L+1};
            down[chi[now][0]]=down[chi[now][1]]=1;
        }
        else
        {
            add(w[chi[now][0]],1);//lc=(data){lc.L,lc.R,0,lc.R-lc.L+1,0,0,0};
            add(w[chi[now][1]],1);//rc=(data){rc.L,rc.R,0,rc.R-rc.L+1,0,0,0};
            down[chi[now][0]]=down[chi[now][1]]=2;
        }
        down[now]=0;
    }
    return ;
}
void build(int &now,int L,int R)
{
    now=++np;
    if(L==R)
    {
        w[now]=(data){L,R,0,1,0,0,0}; return ;
    }
    int m=(L+R)>>1;
    build(chi[now][0],L,m); build(chi[now][1],m+1,R);
    pushup(w[now],w[chi[now][0]],w[chi[now][1]]);
    return ;
}
void update(int now,int L,int R,int x,int y,int v)
{
    if(x>y)return ;
    if(x<=L && R<=y)
    {
        down[now]=v+1;
        add(w[now],v);
        return ;
    }
    int m=(L+R)>>1;
    pushdown(now);
    if(x<=m)update(chi[now][0],L,m,x,y,v);
    if(y> m)update(chi[now][1],m+1,R,x,y,v);
    pushup(w[now],w[chi[now][0]],w[chi[now][1]]);
    return ;
}
int Num;
void fix(int now,int L,int R,int x,int y)
{
    if(!Num)return ;
    if(x<=L && R<=y && Num>=w[now].Sum0)
    {
        Num-=w[now].Sum0;
        add(w[now],1);
        down[now]=2;
        return ;
    }
    int m=(L+R)>>1;
    pushdown(now);
    if(x<=m)fix(chi[now][0],L,m,x,y);
    if(y> m)fix(chi[now][1],m+1,R,x,y);
    pushup(w[now],w[chi[now][0]],w[chi[now][1]]);
    return ;
}
data query(int now,int L,int R,int x,int y)
{
    if(x<=L && R<=y)
    {
        return w[now];
    }
    pushdown(now);
    //pushup(w[now],w[chi[now][0]],w[chi[now][1]]);
    int m=(L+R)>>1;
    if(y<=m)
    {
        return query(chi[now][0],L,m,x,y);
    }
    else if(x>m)
    {
        return query(chi[now][1],m+1,R,x,y);
    }
    else
    {
        data t;
        pushup(t,query(chi[now][0],L,m,x,y),query(chi[now][1],m+1,R,x,y));
        return t;
    }
}
void Debug(data x)
{
//  printf("%d %d : %d %d %d %d %d\n",x.L,x.R,x.Sum0,x.Sum1,x.lmax,x.rmax,x.max);
    return ;
}
void Debug2()
{
/*  data t;
    for(int i=1;i<=N;i++)
    {
        t=query(rt,1,N,i,i);
        printf("%d ",t.Sum1);
    }
    putchar('\n');*/
}
void work()
{
    _read(N);_read(M);
    build(rt,1,N);
    char op;int xa,ya,xb,yb,L,R,mid,ans;data A,B,C;
    for(int i=1;i<=M;i++)
    {
        op=getchar(); while(op!='0' && op!='1' && op!='2')op=getchar();
        if(op=='0')
        {
            _read(xa); _read(ya);
            update(rt,1,N,xa,ya,0);
        }
        else if(op=='1')
        {
            _read(xa); _read(ya); A=query(rt,1,N,xa,ya);
            _read(xb); _read(yb); B=query(rt,1,N,xb,yb);
            update(rt,1,N,xa,ya,0);
            Num=A.Sum1;
            fix(rt,1,N,xb,yb);
        }
        else
        {
            _read(xa); _read(ya); A=query(rt,1,N,xa,ya);
        //  Debug(A);
            printf("%d\n",A.max);
        }
    //  Debug2();
    }
    return ;
}
int main()
{
    //freopen("in.txt","r",stdin);
    work();
    return 0;
}
(我必須承認最開始我想的是再來一層二分。。。)