码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

时间:2017-08-12 20:33:47      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:clu   com   algorithm   freopen   enter   最小   return   click   memory   

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\n",order(1,l,r,k)+1);
        }
        else if(opt==2)
        {
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",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\n",Segment_getpre(1,l,r,k));
        }
        else
        {
            scanf("%d%d%d",&l,&r,&k);
            printf("%d\n",Segment_getsuc(1,l,r,k));
        }
    }
}

 

一组良心数据

技术分享
200 50 
9752845 3933327 3758833 1595009 8083905 7970905 1201113 684481 9688065 9546525 9858065 8628702 5111937 6978005 4629572 6164673 9666565 672665 8777985 1348341 6737219 1655217 3471546 7182725 9181357 3989081 5522679 9428397 2734677 1261825 1141907 6573497 2181575 2958353 9794155 1141661 2599129 2881129 8872845 1670079 1555871 6219245 261083 2841745 7844813 3957317 4379681 3288609 5867317 9692913 5696241 6751841 2290249 8866497 4339441 4648737 6786949 8554506 2956627 5612585 9720261 9513355 4374913 4795959 9202361 5119957 2252769 1881525 2877089 5539070 5957169 4385502 388577 7354707 2254841 4162925 2308913 9708717 742393 5214347 5772341 7475713 8533875 9300737 8288833 7648793 2857109 3663369 9459123 9271629 2440037 8643329 6115777 7517357 1919369 8097009 1651367 6344065 2596527 3307619 8398065 6531345 5882065 3049723 8780177 6401723 7944481 6754945 8486865 8273409 152429 1737240 3022529 9995355 651169 5673918 9787437 9491377 9843781 9388017 8066577 7456097 8784951 736913 7716435 7555634 3719585 303881 9036625 2327037 7458735 7456417 6540145 2628973 981329 8660673 4308169 3439217 1174221 608625 3980981 5401549 5551189 8278639 2324745 2742539 1303169 2120645 4783885 1532545 9704603 2387693 3911705 3516405 4510145 4190603 5424147 7919067 368225 3251545 6016513 7715824 2662817 3099216 7345939 4907153 1529530 1855969 2477809 4830961 5718113 7250323 1382289 2845989 4873627 1050843 8649385 2905697 5798657 9661965 5918577 8395869 2221377 7522809 1765069 2542493 5519599 318867 9665785 1 1642225 6936761 5305629 2696801 2458001 3839230 7365311 1758488 6382541 3323114 
2 35 145 93 
5 46 199 5915878 
4 110 161 6017828 
4 49 93 6792998 
5 41 105 6783428 
2 55 113 4 
5 61 179 7250122 
3 169 2351098 
5 13 97 740944 
1 3 80 4374913 
5 56 170 4384493 
5 35 121 1546226 
2 41 65 7 
5 47 172 8639218 
2 4 149 133 
4 10 137 8869418 
5 25 136 8870300 
4 15 86 8563303 
5 35 162 9686648 
2 33 178 102 
4 31 132 9467468 
1 33 160 8533875 
5 57 176 6531630 
2 31 112 63 
2 49 129 9 
5 29 160 8530626 
5 19 106 3656096 
2 21 146 121 
1 69 109 5772341 
3 169 1920193 
1 105 177 6540145 
5 52 85 1876709 
2 153 177 22 
2 53 81 24 
1 23 110 3307619 
3 146 5015665 
5 45 162 2324995 
5 71 182 4302867 
2 4 199 131 
4 27 120 2255246 
5 17 126 5858724 
1 132 139 6540145 
1 62 147 388577 
3 17 3448561 
3 165 1280715 
4 45 197 3520518 
3 1 6365547 
4 24 125 4655599 
1 27 122 6219245 
1 1 148 2252769
View Code

 

bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

标签:clu   com   algorithm   freopen   enter   最小   return   click   memory   

原文地址:http://www.cnblogs.com/TheRoadToTheGold/p/7351260.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!