zoukankan      html  css  js  c++  java
  • 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
    ",ans[i]*(ans[i]<0?-1:1));
        return 0;
    }
  • 相关阅读:
    通过DataSet操作XML
    什么是网站流量
    JavaScript总结(2)网页上显示时间
    对xml操作的主要方法
    xml保存图片和读取图片(三)
    SharePoint初探sharepoint 安装宝典(2)
    SharePoint初探启用wss的全文搜索(6)
    转载:sharepoint portal server2003安装小记
    SharePoint初探装完Wss后,无法创建或打开原有Web项目问题(7)
    SharePoint初探SharePoint网站整理(8)
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10201444.html
Copyright © 2011-2022 走看看