• BZOJ 3196: Tyvj 1730 二逼平衡树


    3196: Tyvj 1730 二逼平衡树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 3033  Solved: 1201
    [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可能为负数

    Source

    分析:

    线段树套平衡树...

    对于2操作就可以二分那个数字是区间第k大,然后查询当前数字再区间中的排名,不需要判断这个数字是否存在于区间中是因为所有排名合法的数字中最大的那个一定是答案...

    比较忧伤的是写了线段树套Splay才知道我的线段树和Splay的常数有多大QAQ...

    哎,没办法人帅自带大常数^_~...

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 //by NeighThorn
      6 #define inf 1e8+8
      7 using namespace std;
      8 
      9 const int maxn=50000*70+5,maxm=50000+5;
     10 
     11 int n,m,opt,a[maxm];
     12 
     13 int w[maxn],ls[maxn],rs[maxn],fa[maxn],cnt[maxn],siz[maxn],tot;
     14 
     15 inline int read(void){
     16     char ch=getchar();int x=0,f=1;
     17     while(!(ch>='0'&&ch<='9')){
     18         if(ch=='-')
     19             f=-1;
     20         ch=getchar();
     21     }
     22     while(ch>='0'&&ch<='9')
     23         x=x*10+ch-'0',ch=getchar();
     24     return x*f;
     25 }
     26 
     27 struct Splay{
     28     
     29     int root;
     30 
     31     inline void zig(int x){
     32         int y=fa[x],tmp=siz[y];
     33         if(rs[x])
     34             ls[y]=rs[x],fa[rs[x]]=y,siz[y]=siz[y]-siz[x]+siz[rs[x]],siz[x]=tmp;
     35         else
     36             ls[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp;
     37         fa[x]=fa[y];
     38         if(fa[x]){
     39             if(ls[fa[x]]==y)
     40                 ls[fa[x]]=x;
     41             else
     42                 rs[fa[x]]=x;
     43         }
     44         fa[y]=x,rs[x]=y;
     45     }
     46     
     47     inline void zag(int x){
     48         int y=fa[x],tmp=siz[y];
     49         if(ls[x])
     50             rs[y]=ls[x],fa[ls[x]]=y,siz[y]=siz[y]-siz[x]+siz[ls[x]],siz[x]=tmp;
     51         else
     52             rs[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp;
     53         fa[x]=fa[y];
     54         if(fa[x]){
     55             if(ls[fa[x]]==y)
     56                 ls[fa[x]]=x;
     57             else
     58                 rs[fa[x]]=x;
     59         }
     60         fa[y]=x,ls[x]=y;
     61     }
     62     
     63     inline void splay(int x,int z){
     64         while(fa[x]!=z){
     65             int y=fa[x];
     66             if(fa[y]==z){
     67                 if(ls[y]==x)
     68                     zig(x);
     69                 else
     70                     zag(x);
     71             }
     72             else{
     73                 if(ls[fa[y]]==y){
     74                     if(ls[y]==x)
     75                         zig(y),zig(x);
     76                     else
     77                         zag(x),zig(x);
     78                 }
     79                 else{
     80                     if(rs[y]==x)
     81                         zag(y),zag(x);
     82                     else
     83                         zig(x),zag(x);
     84                 }
     85             }
     86         }
     87         if(!z)
     88             root=x;
     89     }
     90     
     91     inline void ins(int rt,int x){
     92         if(!rt)
     93             w[++tot]=x,siz[tot]=cnt[tot]=1,root=tot;
     94         else{
     95             while(!(w[rt]==x||(x<w[rt]&&!ls[rt])||(x>w[rt]&&!rs[rt]))){
     96                 if(x<w[rt])
     97                     siz[rt]++,rt=ls[rt];
     98                 else if(x>w[rt])
     99                     siz[rt]++,rt=rs[rt];
    100             }
    101             if(w[rt]==x)
    102                 siz[rt]++,cnt[rt]++,splay(rt,0);
    103             else if(x<w[rt])
    104                 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,ls[rt]=tot,fa[tot]=rt,splay(tot,0);
    105             else
    106                 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,rs[rt]=tot,fa[tot]=rt,splay(tot,0);
    107         }/*
    108         else if(w[rt]==x)
    109             siz[rt]++,cnt[rt]++,splay(rt,0);
    110         else if(x<w[rt]){
    111             if(!ls[rt])
    112                 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,ls[rt]=tot,fa[tot]=rt,splay(tot,0);
    113             else
    114                 siz[rt]++,ins(ls[rt],x);
    115         }
    116         else{
    117             if(!rs[rt])
    118                 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,rs[rt]=tot,fa[tot]=rt,splay(tot,0);
    119             else
    120                 siz[rt]++,ins(rs[rt],x);
    121         }*/
    122     }
    123     
    124     inline void del(int rt,int x){
    125         while(w[rt]!=x){
    126             if(x<w[rt])
    127                 rt=ls[rt];
    128             else
    129                 rt=rs[rt];
    130         }
    131         splay(rt,0);
    132         if(cnt[rt]>1)
    133             cnt[rt]--,siz[rt]--;
    134         else{
    135             int l=ls[rt],r=rs[rt];
    136             if(!l)
    137                 ls[rt]=rs[rt]=fa[rt]=cnt[rt]=siz[rt]=0,fa[r]=0,root=r;
    138             else{
    139                 while(rs[l])
    140                     l=rs[l];
    141                 splay(l,rt);ls[rt]=rs[rt]=fa[rt]=cnt[rt]=siz[rt]=0;fa[r]=l,rs[l]=r,siz[l]+=siz[r];root=l,fa[l]=0;
    142             }
    143         }
    144     }
    145     
    146     inline int pre(int rt,int x){
    147         int res=-inf;
    148         while(rt){
    149             if(w[rt]<x)
    150                 res=max(res,w[rt]),rt=rs[rt];
    151             else
    152                 rt=ls[rt];
    153         }
    154         return res;
    155     }
    156     
    157     inline int suf(int rt,int x){
    158         int res=inf;
    159         while(rt){
    160             if(w[rt]>x)
    161                 res=min(res,w[rt]),rt=ls[rt];
    162             else
    163                 rt=rs[rt];
    164         }
    165         return res;
    166     }
    167     
    168     inline int rank(int rt,int x){
    169         while(w[rt]!=x){
    170             if(x<w[rt])
    171                 rt=ls[rt];
    172             else
    173                 rt=rs[rt];
    174         }
    175         splay(rt,0);
    176         if(!ls[rt])
    177             return 1;
    178         else
    179             return siz[ls[rt]]+1;
    180     }
    181     
    182     inline int query(int rt,int x){
    183         if(!ls[rt]){
    184             if(cnt[rt]>=x){
    185                 splay(rt,0);
    186                 return w[rt];
    187             }
    188             else
    189                 return query(rs[rt],x-cnt[rt]);
    190         }
    191         else{
    192             if(siz[ls[rt]]>=x)
    193                 return query(ls[rt],x);
    194             else if(siz[ls[rt]]+cnt[rt]>=x){
    195                 splay(rt,0);
    196                 return w[rt];
    197             }
    198             else
    199                 return query(rs[rt],x-siz[ls[rt]]-cnt[rt]);
    200         }
    201     }
    202     
    203 };
    204 
    205 struct Tree{
    206     int l,r;
    207     Splay s;
    208 }tree[maxm*4];
    209 
    210 inline void build(int l,int r,int tr){
    211     tree[tr].l=l,tree[tr].r=r;
    212     for(int i=l;i<=r;i++)
    213         tree[tr].s.ins(tree[tr].s.root,a[i]);
    214     if(l==r)
    215         return;
    216     int mid=(l+r)>>1;
    217     build(l,mid,tr<<1);build(mid+1,r,tr<<1|1);
    218 }
    219 /*
    220 inline void insert(int tr,int pos,int x){
    221     tree[tr].s.ins(tree[tr].s.root,x);
    222     if(tree[tr].l==tree[tr].r)
    223         return;
    224     int mid=(tree[tr].l+tree[tr].r)>>1;
    225     if(pos<=mid)
    226         insert(tr<<1,pos,x);
    227     else
    228         insert(tr<<1|1,pos,x);
    229 }
    230 */
    231 inline int qryrank(int tr,int l,int r,int x){
    232     int lala;
    233     if(tree[tr].l==l&&tree[tr].r==r)
    234         return tree[tr].s.ins(tree[tr].s.root,x),lala=tree[tr].s.rank(tree[tr].s.root,x)-1,tree[tr].s.del(tree[tr].s.root,x),lala;
    235     int mid=(tree[tr].l+tree[tr].r)>>1;
    236     if(r<=mid)
    237         return qryrank(tr<<1,l,r,x);
    238     else if(l>mid)
    239         return qryrank(tr<<1|1,l,r,x);
    240     else
    241         return qryrank(tr<<1,l,mid,x)+qryrank(tr<<1|1,mid+1,r,x);
    242 }
    243 
    244 inline void change(int tr,int pos,int x){
    245     tree[tr].s.del(tree[tr].s.root,a[pos]),tree[tr].s.ins(tree[tr].s.root,x);
    246     if(tree[tr].l==tree[tr].r)
    247         return;
    248     int mid=(tree[tr].l+tree[tr].r)>>1;
    249     if(pos<=mid)
    250         change(tr<<1,pos,x);
    251     else
    252         change(tr<<1|1,pos,x);
    253 }
    254 
    255 inline int qrypre(int tr,int l,int r,int x){
    256     if(tree[tr].l==l&&tree[tr].r==r)
    257         return tree[tr].s.pre(tree[tr].s.root,x);
    258     int mid=(tree[tr].l+tree[tr].r)>>1;
    259     if(r<=mid)    
    260         return qrypre(tr<<1,l,r,x);
    261     else if(l>mid)
    262         return qrypre(tr<<1|1,l,r,x);
    263     else
    264         return max(qrypre(tr<<1,l,mid,x),qrypre(tr<<1|1,mid+1,r,x));
    265 }
    266 
    267 inline int qrysuf(int tr,int l,int r,int x){
    268     if(tree[tr].l==l&&tree[tr].r==r)
    269         return tree[tr].s.suf(tree[tr].s.root,x);
    270     int mid=(tree[tr].l+tree[tr].r)>>1;
    271     if(r<=mid)
    272         return qrysuf(tr<<1,l,r,x);
    273     else if(l>mid)
    274         return qrysuf(tr<<1|1,l,r,x);
    275     else
    276         return min(qrysuf(tr<<1,l,mid,x),qrysuf(tr<<1|1,mid+1,r,x));
    277 }
    278 
    279 signed main(void){
    280 //    freopen("3196.in","r",stdin);
    281 //    freopen("3196.out","w",stdout);
    282     memset(ls,0,sizeof(ls));
    283     memset(rs,0,sizeof(rs));
    284     memset(fa,0,sizeof(fa));
    285     memset(cnt,0,sizeof(cnt));
    286     memset(siz,0,sizeof(siz));
    287     n=read(),m=read();
    288     for(int i=1;i<=n;i++)
    289         a[i]=read();//,insert(1,i,a[i]);
    290     build(1,n,1);
    291     for(int i=1,l,r,x;i<=m;i++){
    292         opt=read();
    293         if(opt==1){
    294             l=read(),r=read(),x=read();
    295             printf("%d
    ",qryrank(1,l,r,x)+1);
    296         }
    297         else if(opt==2){
    298             l=read(),r=read(),x=read();
    299             int lef=1,rig=n,ans;
    300             while(lef<=rig){
    301                 int mid=(lef+rig)>>1,tmp=tree[1].s.query(tree[1].s.root,mid);
    302                 if(qryrank(1,l,r,tmp)<=x-1)
    303                     lef=mid+1,ans=tmp;
    304                 else
    305                     rig=mid-1;
    306             }
    307             printf("%d
    ",ans);
    308         }
    309         else if(opt==3){
    310             l=read(),x=read();
    311             change(1,l,x);a[l]=x;
    312         }
    313         else if(opt==4){
    314             l=read(),r=read(),x=read();
    315             printf("%d
    ",qrypre(1,l,r,x));
    316         }
    317         else if(opt==5){
    318             l=read(),r=read(),x=read();
    319             printf("%d
    ",qrysuf(1,l,r,x));
    320         }
    321     }
    322     return 0;
    323 }
    View Code

    by NeighThorn

  • 相关阅读:
    uva694 The Collatz Sequence
    WindowsPhone7开发简单豆瓣网应用程序之主页面功能实现
    使用codeplex管理WP7项目开发版本
    WindowsPhone7开发简单豆瓣网应用程序之界面设计
    WindowsPhone操作SkyDrive之获取共享文件
    Windows Phone7监测网络接口及状态变化
    《设计模式》杂记之里氏替换原则
    Silverlight杂记之HTTP通信WebClient介绍
    WindowsPhone获取是否进行拨电话信息[使用PhoneCallTask]
    《设计模式》杂记之单一职责原则
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6163303.html
Copyright © 2020-2023  润新知