bzoj3196 Tyvj 1730 二逼平衡树

题目描述

题解:

看到网上几乎全是树套树,

我就写了个整体二分。

其中操作1,2,3一般整体二分都能做到。

对于前驱,我们只需要在线段树中多维护区间最大值即可;

对于后继……

通通取反后再跑一遍查询前驱即可。

然后迷之卡空间。

最后迷之卡过。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 500050
const int inf = 0x3f3f3f3f;
inline int rd()
{
    int f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
    return f*c;
}
int n,m,tot,cnt,qcnt,ans[N],vl[N],mx,to[5*N/2];
struct node
{
    int opt,id;
    int l,r,k;
    int num;
}p[5*N/2],tmpl[5*N/2],tmpr[5*N/2];
bool nmp(node a,node b)
{
    return a.num<b.num;
}
struct Pair
{
    int x,id;
    Pair(){}
    Pair(int x,int i):x(x),id(i){}
}o[5*N/2];
bool cmp(Pair a,Pair b)
{
    return a.x<b.x;
}
struct segtree
{
    int siz[5*N/2],sum[5*N/2],tag[5*N/2],mx[5*N/2];
    bool rec[5*N/2];
    void add(int u,int d)
    {
        tag[u]+=d;
        sum[u]+=siz[u]*d;
    }
    void rece(int u)
    {
        sum[u]=tag[u]=0;
        mx[u]=-inf;
        rec[u]=1;
    }
    void pushdown(int u)
    {
        if(rec[u])
        {
            rece(u<<1);
            rece(u<<1|1);
            rec[u]=0;
        }
        if(tag[u])
        {
            add(u<<1,tag[u]);
            add(u<<1|1,tag[u]);
            tag[u] = 0;
        }
    }
    void update(int u)
    {
        mx[u] = max(mx[u<<1],mx[u<<1|1]);
        sum[u] = sum[u<<1]+sum[u<<1|1];
    }
    void build(int l,int r,int u)
    {
        siz[u] = r-l+1;
        mx[u] = -inf;
        if(l==r)return ;
        int mid = (l+r)>>1;
        build(l,mid,u<<1);
        build(mid+1,r,u<<1|1);
    }
    void insert(int l,int r,int u,int qx,int qd,int d)
    {
        if(l==r)
        {
            sum[u] += d;
            if(!sum[u])mx[u]=-inf;
            else mx[u] = qd;
            return ;
        }
        pushdown(u);
        int mid = (l+r)>>1;
        if(qx<=mid)insert(l,mid,u<<1,qx,qd,d);
        else insert(mid+1,r,u<<1|1,qx,qd,d);
        update(u);
    }
    int q1(int l,int r,int u,int ql,int qr)
    {
        if(l==ql&&r==qr)return sum[u];
        pushdown(u);
        int mid = (l+r)>>1;
        if(qr<=mid)return q1(l,mid,u<<1,ql,qr);
        else if(ql>mid)return q1(mid+1,r,u<<1|1,ql,qr);
        else return q1(l,mid,u<<1,ql,mid)+q1(mid+1,r,u<<1|1,mid+1,qr);
    }
    int q2(int l,int r,int u,int ql,int qr)
    {
        if(l==ql&&r==qr)return mx[u];
        pushdown(u);
        int mid = (l+r)>>1;
        if(qr<=mid)return q2(l,mid,u<<1,ql,qr);
        else if(ql>mid)return q2(mid+1,r,u<<1|1,ql,qr);
        else return max(q2(l,mid,u<<1,ql,mid),q2(mid+1,r,u<<1|1,mid+1,qr));
    }
}tr;
void divi(int l,int r,int beg,int ens)
{
    if(beg>ens)return ;
    if(l==r)
    {
        for(int i=beg;i<=ens;i++)
            if(p[i].opt==2)ans[p[i].id]=to[l];
        return ;
    }
    int mid = (l+r)>>1;
    int lt = 0,rt = 0;
    bool l1 = 0,r1 = 0;
    tr.rece(1);
    for(int i=beg;i<=ens;i++)
    {
        if(p[i].opt==0)
        {
            if(p[i].k<=mid)
            {
                tr.insert(1,n,1,p[i].id,to[p[i].k],1);
                tmpl[++lt] = p[i];
            }else tmpr[++rt] = p[i];
        }else if(p[i].opt==1)
        {
            if(p[i].k>mid)
            {
                ans[p[i].id]+=tr.q1(1,n,1,p[i].l,p[i].r);
                tmpr[++rt] = p[i];r1=1;
            }else tmpl[++lt] = p[i],l1=1;
        }else if(p[i].opt==2)
        {
            int now = tr.q1(1,n,1,p[i].l,p[i].r);
            if(now<p[i].k)
            {
                p[i].k-=now;
                tmpr[++rt] = p[i];r1=1;
            }else tmpl[++lt] = p[i],l1=1;
        }else if(p[i].opt==3)
        {
            if(p[i].k<=mid)
            {
                tr.insert(1,n,1,p[i].id,to[p[i].k],-1);
                tmpl[++lt] = p[i];
            }else tmpr[++rt] = p[i];
        }else if(p[i].opt==4)
        {
            if(p[i].k>mid)
            {
                ans[p[i].id] = max(ans[p[i].id],tr.q2(1,n,1,p[i].l,p[i].r));
                tmpr[++rt] = p[i];r1=1;
            }else tmpl[++lt] = p[i],l1=1;
        }else tmpr[++rt] = p[i];
    }
    for(int i=beg;i<=beg+lt-1;i++)p[i]=tmpl[i-beg+1];
    for(int i=beg+lt;i<=ens;i++)p[i]=tmpr[i-beg-lt+1];
    if(l1)divi(l,mid,beg,beg+lt-1);
    if(r1)divi(mid+1,r,beg+lt,ens);
}
void dv(int l,int r,int beg,int ens)
{
    if(beg>ens)return ;
    if(l==r)return ;
    int mid = (l+r)>>1;
    int lt = 0,rt = 0,i;
    bool l1 = 0,r1 = 0;
    tr.rece(1);
    for(i=beg;i<=ens;i++)
    {
        if(p[i].opt==0)
        {
            if(-p[i].k<=mid)
            {
                tr.insert(1,n,1,p[i].id,-to[p[i].k],1);
                tmpl[++lt] = p[i];
            }else tmpr[++rt] = p[i];
        }else if(p[i].opt==3)
        {
            if(-p[i].k<=mid)
            {
                tr.insert(1,n,1,p[i].id,-to[p[i].k],-1);
                tmpl[++lt] = p[i];
            }else tmpr[++rt] = p[i];
        }else if(p[i].opt==5)
        {
            if(-p[i].k>mid)
            {
                int tmp = tr.q2(1,n,1,p[i].l,p[i].r);
                if(tmp!=-inf)ans[p[i].id] = max(ans[p[i].id],tmp);
                tmpr[++rt] = p[i];r1=1;
            }else tmpl[++lt] = p[i],l1=1;
        }
    }
    for(i=beg;i<=beg+lt-1;i++)p[i]=tmpl[i-beg+1];
    for(i=beg+lt;i<=beg+lt+rt-1;i++)p[i]=tmpr[i-beg-lt+1];
    if(l1)dv(l,mid,beg,beg+lt-1);
    if(r1)dv(mid+1,r,beg+lt,beg+lt+rt-1);
}
int main()
{
//    freopen("7.in","r",stdin);
    tot = n = rd(),m = rd();
    for(int i=1;i<=n;i++)
    {
        vl[i] = rd();
        p[i].id = i;
        o[++cnt] = Pair(vl[i],i);
    }
    for(int opt,l,r,k,id,i=1;i<=m;i++)
    {
        opt = rd(),tot++;p[tot].opt = opt;
        if(opt==3)id=rd(),k=rd();
        else l=rd(),r=rd(),k=rd();
        if(opt==1||opt==4||opt==5)p[tot].l=l,p[tot].r=r,o[++cnt]=Pair(k,tot),p[tot].id=++qcnt;
        if(opt==2)p[tot].l=l,p[tot].r=r,p[tot].k=k,p[tot].id=++qcnt;
        if(opt==3)
        {
            p[tot].id = id;o[++cnt]=Pair(vl[id],tot);
            tot++;
            p[tot].id = id;o[++cnt]=Pair(k,tot);
            vl[id] = k;
        }
        if(opt==1)ans[qcnt]=1;
        if(opt>=4)ans[qcnt]=-inf;
    }
    sort(o+1,o+1+cnt,cmp);
    for(int las=inf,i=1;i<=cnt;i++)
    {
        if(las!=o[i].x)
        {
            las = o[i].x;
            to[++mx] = las;
        }
        p[o[i].id].k = mx;
    }
    for(int i=1;i<=tot;i++)p[i].num=i;
    tr.build(1,n,1);
    divi(1,mx,1,tot);
    sort(p+1,p+1+tot,nmp);
    dv(-mx,-1,1,tot);
    for(int i=1;i<=qcnt;i++)
        printf("%d\n",ans[i]*(ans[i]<0?-1:1));
    return 0;
}

 

posted @ 2018-12-31 09:52  LiGuanlin  阅读(137)  评论(0编辑  收藏  举报