zoukankan      html  css  js  c++  java
  • bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    [Submit][Status][Discuss]

    Description

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
    1.查询k在区间内的排名
    2.查询区间内排名为k的值
    3.修改某一位值上的数值
    4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
    5.查询k在区间内的后继(后继定义为大于x,且最小的数)

    Input

    第一行两个数 n,m 表示长度为n的有序序列和m个操作
    第二行有n个数,表示有序序列
    下面有m行,opt表示操作标号
    若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
    若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
    若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
    若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
    若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

    Output

    对于操作1,2,4,5各输出一行,表示查询结果

    Sample Input

    9 6
    4 2 2 1 9 4 0 1 1
    2 1 4 3
    3 4 10
    2 1 4 3
    1 2 5 9
    4 3 9 5
    5 2 8 5

    Sample Output

    2
    4
    3
    4
    9

    HINT

    1.n和m的数据范围:n,m<=50000


    2.序列中每个数的数据范围:[0,1e8]


    3.虽然原题没有,但事实上5操作的k可能为负数
     
    线段树套平衡树
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define M 3000001
    #define N 50001
    
        int id=0;
        int siz[M],cnt[M],key[M];
        int fa[M],ch[M][2];
        struct TREE
        {
            int root,l,r;
        }tr[N<<2];
        int data[N];
        void Splay_up(int k)
        {
            siz[k]=siz[ch[k][0]]+siz[ch[k][1]]+cnt[k];
        }
        void rotate(int x,int &goal)
        {
            int y=fa[x],z=fa[y];
            int l=ch[y][1]==x,r=l^1;
            if(y==goal) goal=x;
            else ch[z][ch[z][1]==y]=x;
            ch[y][l]=ch[x][r]; ch[x][r]=y; 
            fa[x]=z; fa[y]=x; fa[ch[y][l]]=y;
            Splay_up(y);
        }
        void splay(int x,int &goal)
        {
            int y,z;
            while(x!=goal)
            {
                y=fa[x]; z=fa[y];
                if(y!=goal) 
                {
                    if(ch[z][0]==y ^ ch[y][0]==x) rotate(x,goal);
                    else rotate(y,goal);
                }
                rotate(x,goal);
                Splay_up(x);
            }
        }
        void Splay_insert(int &rt,int w)
        {    
            if(!rt)
            {
                rt=++id;
                siz[rt]=cnt[rt]=1;
                key[rt]=w;
                return;
            }
            if(key[rt]==w) cnt[rt]++;
            else if(w<key[rt]) Splay_insert(ch[rt][0],w),fa[ch[rt][0]]=rt;
            else Splay_insert(ch[rt][1],w),fa[ch[rt][1]]=rt;
            Splay_up(rt);
        }
        int Splay_getpre(int rt,int x)
        {
            int now=rt,ret;
            while(now)
            {
                if(key[now]>=x) now=ch[now][0];
                else ret=now,now=ch[now][1];
            }
            return ret;
        }
        int Splay_getsuc(int rt,int x)
        {
            int now=rt,ret;
            while(now)
            {
                if(key[now]<=x) now=ch[now][1];
                else ret=now,now=ch[now][0];
            }
            return ret;
        }
        int Splay_number(int now,int w)
        {
            while(1)
            {
                if(key[now]==w) return now;
                if(w<key[now]) now=ch[now][0];
                else now=ch[now][1];
            }
        }
        void del(int & rt,int w)
        {
            int num=Splay_number(rt,w);
            splay(num,rt);
            if(cnt[num]>1) cnt[num]--, siz[num]--;
            else
            {
                int pre=Splay_getpre(rt,w);
                splay(pre,rt);
                ch[pre][1]=ch[num][1];
                fa[ch[pre][1]]=pre;
                Splay_up(pre);
            }
        }
        void add_dummy(int rt,int w,int d)
        {
            ch[rt][d]=++id; siz[rt]++;
            fa[id]=rt; siz[id]=cnt[id]=1; key[id]=w;
        }
        
        void build(int k,int l,int r)
        {
            tr[k].l=l; tr[k].r=r;
            if(l==r) return;
            int mid=l+r>>1;
            build(k<<1,l,mid); 
            build(k<<1|1,mid+1,r);    
        }
        void Segment_insert(int k,int pos,int w)
        {
             Splay_insert(tr[k].root,w);
            if(tr[k].l==tr[k].r) return;
            int mid=tr[k].l+tr[k].r>>1;
            if(pos<=mid) Segment_insert(k<<1,pos,w);
            else Segment_insert(k<<1|1,pos,w);
        }
        void dummy(int k)
        {
            int pre=Splay_getsuc(tr[k].root,-1),suc=Splay_getpre(tr[k].root,1e8);
            splay(pre,tr[k].root);
            add_dummy(pre,-1e8-1,0);
            splay(suc,tr[k].root);
            add_dummy(suc,1e8+1,1);
            if(tr[k].l==tr[k].r) return;
            dummy(k<<1); dummy(k<<1|1);
        }
        int order(int k,int opl,int opr,int w)
        {
            if(tr[k].l>=opl && tr[k].r<=opr)
            {
                int pre=Splay_getpre(tr[k].root,w);
                splay(pre,tr[k].root);
                return siz[ch[pre][0]]+cnt[pre]-1;
            }
            int mid=tr[k].l+tr[k].r>>1,tmp=0;
            if(opl<=mid) tmp+=order(k<<1,opl,opr,w);
            if(opr>mid) tmp+=order(k<<1|1,opl,opr,w);
            return tmp;
        }
        int Segment_number(int l,int r,int w)
        {
            int ll=1,rr=1e8,mid,tmp,ans;
            while(ll<=rr)
            {
                mid=ll+rr>>1;
                tmp=order(1,l,r,mid);
                if(tmp<w) ans=mid,ll=mid+1;
                else rr=mid-1;
            }
            return ans;
        }
        void modify(int k,int pos,int before,int now)
        {
            del(tr[k].root,before);
            Splay_insert(tr[k].root,now);
            if(tr[k].l==tr[k].r)
            {
                data[tr[k].l]=now;
                return;
            }
            int mid=tr[k].l+tr[k].r>>1;
            if(pos<=mid) modify(k<<1,pos,before,now);
            else modify(k<<1|1,pos,before,now);
        }
        int Segment_getpre(int k,int l,int r,int w)
        {
            if(tr[k].l>=l && tr[k].r<=r) return key[Splay_getpre(tr[k].root,w)];
            int mid=tr[k].l+tr[k].r>>1,tmp=-1e8-1;
            if(l<=mid) tmp=max(tmp,Segment_getpre(k<<1,l,r,w));
            if(r>mid) tmp=max(tmp,Segment_getpre(k<<1|1,l,r,w));
            return tmp; 
        }
        int Segment_getsuc(int k,int l,int r,int w)
        {
            if(tr[k].l>=l && tr[k].r<=r) return key[Splay_getsuc(tr[k].root,w)];
            int mid=tr[k].l+tr[k].r>>1,tmp=1e8+1; 
            if(l<=mid) tmp=min(tmp,Segment_getsuc(k<<1,l,r,w));
            if(r>mid) tmp=min(tmp,Segment_getsuc(k<<1|1,l,r,w));
            return tmp;
         }
         
    int main()
    {
        freopen("psh.in","r",stdin);
        freopen("psh.out","w",stdout);
        int n,m;
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int i=1;i<=n;i++) 
        {
            scanf("%d",&data[i]); 
            Segment_insert(1,i,data[i]);
        }
        dummy(1);
        int opt,l,r,k;
        while(m--)
        {
            scanf("%d",&opt);
            if(opt==1)
            {
                scanf("%d%d%d",&l,&r,&k);
                printf("%d
    ",order(1,l,r,k)+1);
            }
            else if(opt==2)
            {
                scanf("%d%d%d",&l,&r,&k);
                printf("%d
    ",Segment_number(l,r,k));
            }
            else if(opt==3)
            {
                scanf("%d%d",&l,&k);
                modify(1,l,data[l],k);
            }
            else if(opt==4)
            {
                scanf("%d%d%d",&l,&r,&k);
                printf("%d
    ",Segment_getpre(1,l,r,k));
            }
            else
            {
                scanf("%d%d%d",&l,&r,&k);
                printf("%d
    ",Segment_getsuc(1,l,r,k));
            }
        }
    }

     

  • 相关阅读:
    淘宝质量属性场景分析
    关于软件架构师如何工作(阅读架构漫谈感悟)
    06有效需求设计阅读笔记之六
    05有效需求设计阅读笔记之五
    xxx征集系统项目目标文档
    04有效需求设计阅读笔记之四
    03有效需求设计阅读笔记之三
    02有效需求设计阅读笔记之二
    01有效需求设计阅读笔记之一
    问题账户需求分析
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7351260.html
Copyright © 2011-2022 走看看