BZOJ 4592 脑洞治疗仪

Posted on 2017-02-20 21:53  ziliuziliu  阅读(217)  评论(0编辑  收藏  举报

天啦噜我自己YY的从任意起点开始的线段树上二分居然是对的。。。。

好感动啊。

4.7k的代码只调了一个晚上好感动。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200500
using namespace std;
int n,m,sum[maxn<<2],lazy[maxn<<2],ls[maxn<<2],rs[maxn<<2],tot=0,root,l[maxn<<2],r[maxn<<2],mx[maxn<<2];
int type,l1,r1,l2,r2;
struct status
{
    int mx,l,r,len;
    status (int mx,int l,int r,int len):mx(mx),l(l),r(r),len(len) {}
    status () {}
};
void build(int &now,int left,int right)
{
    now=++tot;sum[now]=right-left+1;lazy[now]=-1;
    if (left==right) return;
    int mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
}
void pushdown(int now,int left,int right)
{
    if (lazy[now]==-1) return;
    lazy[ls[now]]=lazy[rs[now]]=lazy[now];
    int mid=(left+right)>>1,ll=mid-left+1,rl=right-mid;
    sum[ls[now]]=lazy[ls[now]]*ll;sum[rs[now]]=lazy[rs[now]]*rl;
    l[ls[now]]=r[ls[now]]=mx[ls[now]]=(lazy[now]^1)*ll;
    l[rs[now]]=r[rs[now]]=mx[rs[now]]=(lazy[now]^1)*rl;
    lazy[now]=-1;
}
void pushup(int now,int left,int right)
{
    sum[now]=sum[ls[now]]+sum[rs[now]];
    int mid=(left+right)>>1,ll=mid-left+1,rl=right-mid;
    if (mx[ls[now]]==ll) l[now]=ll+l[rs[now]];else l[now]=l[ls[now]];
    if (mx[rs[now]]==rl) r[now]=rl+r[ls[now]];else r[now]=r[rs[now]];
    mx[now]=max(r[ls[now]]+l[rs[now]],max(mx[ls[now]],mx[rs[now]]));
}
void modify1(int now,int left,int right,int lq,int rq,int val)
{
    pushdown(now,left,right);
    if (left==lq && right==rq)
    {
        lazy[now]=val;sum[now]=lazy[now]*(right-left+1);
        l[now]=r[now]=mx[now]=(right-left+1)*(val^1);
        return;
    }
    int mid=(left+right)>>1;
    if (rq<=mid) modify1(ls[now],left,mid,lq,rq,val);
    else if (lq>=mid+1) modify1(rs[now],mid+1,right,lq,rq,val);
    else modify1(ls[now],left,mid,lq,mid,val),modify1(rs[now],mid+1,right,mid+1,rq,val);
    pushup(now,left,right);
}
int warn=0;
int modify3(int now,int left,int right,int k)
{
    warn++;
    pushdown(now,left,right);
    int kk=right-left+1-sum[now];
    if (k>=kk)
    {
        sum[now]=right-left+1;lazy[now]=1;
        mx[now]=l[now]=r[now]=0;
        return kk;
    }
    if (left==right)
    {
        sum[now]=1;mx[now]=l[now]=r[now]=0;
        return 1;
    }
    int mid=(left+right)>>1,rr=mid-left+1-sum[ls[now]],ret=0;
    if (k<=rr) ret=modify3(ls[now],left,mid,k);
    else 
    {
        sum[ls[now]]=mid-left+1;lazy[ls[now]]=1;
        mx[ls[now]]=l[ls[now]]=r[ls[now]]=0;
        ret=rr+modify3(rs[now],mid+1,right,k-rr);
    }
    pushup(now,left,right);return ret;
}
int modify2(int now,int left,int right,int l,int r,int k)
{
    warn++;
    pushdown(now,left,right);
    if ((left==l) && (right==r)) return modify3(now,left,right,k);
    int mid=(left+right)>>1,ret=0;
    if (r<=mid) 
    {
        if (mid-left+1-sum[ls[now]]>0)
            ret=modify2(ls[now],left,mid,l,r,k);
    }
    else if (l>=mid+1) 
    {
        if (right-mid-sum[rs[now]]>0)
            ret=modify2(rs[now],mid+1,right,l,r,k);
    }
    else
    {
        if (mid-left+1-sum[ls[now]]) ret=modify2(ls[now],left,mid,l,mid,k);
        if ((k>ret) && (right-mid-sum[rs[now]])) ret+=modify2(rs[now],mid+1,right,mid+1,r,k-ret);
    }
    pushup(now,left,right);return ret;
}
status merge(status x,status y)
{
    status ret=status(0,0,0,0);
    if (x.mx==x.len) ret.l=x.len+y.l;else ret.l=x.l;
    if (y.mx==y.len) ret.r=y.len+x.r;else ret.r=y.r;
    ret.mx=max(x.r+y.l,max(x.mx,y.mx));
    ret.len=x.len+y.len;
    return ret;
}
int ask1(int now,int left,int right,int l,int r)
{
    pushdown(now,left,right);
    if (left==l && right==r) return sum[now];
    int mid=(left+right)>>1;
    if (r<=mid) return ask1(ls[now],left,mid,l,r);
    else if (l>=mid+1) return ask1(rs[now],mid+1,right,l,r);
    else return ask1(ls[now],left,mid,l,mid)+ask1(rs[now],mid+1,right,mid+1,r); 
}
status ask2(int now,int left,int right,int lq,int rq)
{
    pushdown(now,left,right);
    if ((left==lq) && (right==rq)) return status(mx[now],l[now],r[now],right-left+1);
    int mid=(left+right)>>1;
    if (rq<=mid) return ask2(ls[now],left,mid,lq,rq);
    else if (lq>=mid+1) return ask2(rs[now],mid+1,right,lq,rq);
    else return merge(ask2(ls[now],left,mid,lq,mid),ask2(rs[now],mid+1,right,mid+1,rq));
}
int main()
{
    scanf("%d%d",&n,&m);
    build(root,1,n);    
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&type,&l1,&r1);
        if (!type) modify1(root,1,n,l1,r1,0);
        else if (type==1)
        {
            warn=0;
            scanf("%d%d",&l2,&r2);
            int ret=ask1(root,1,n,l1,r1);
            modify1(root,1,n,l1,r1,0);
            if (ret) {int kr=modify2(root,1,n,l2,r2,ret);kr++;}
        }
        else printf("%d\n",ask2(root,1,n,l1,r1).mx);
    }
    return 0;
}