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));
            }
        }
    }

     

  • 相关阅读:
    poj 1579(动态规划初探之记忆化搜索)
    hdu 1133(卡特兰数变形)
    CodeForces 625A Guest From the Past
    CodeForces 625D Finals in arithmetic
    CDOJ 1268 Open the lightings
    HDU 4008 Parent and son
    HDU 4044 GeoDefense
    HDU 4169 UVALive 5741 Wealthy Family
    HDU 3452 Bonsai
    HDU 3586 Information Disturbing
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7351260.html
Copyright © 2011-2022 走看看