zoukankan      html  css  js  c++  java
  • BZOJ3196: Tyvj 1730 二逼平衡树(树套树)

    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

    解题思路:

    其实这道题最简单的做法有两个,第一个区间线段树套Treap,第二个是带修改主席树。

    (整体二分CDQ打腻了打打树套树)

    1.线段树套Treap代码:

      1 #include<ctime>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #define lll spc<<1
      6 #define rrr spc<<1|1
      7 typedef long long lnt;
      8 const int N=1000000;
      9 const int oo=(int)(1e8);
     10 struct trent{
     11     int ls;
     12     int rs;
     13     int val;
     14     int num;
     15     int wgt;
     16     int rnd;
     17 }tr[N],stdtrent;
     18 int n,m;
     19 int ans;
     20 int top;
     21 int siz;
     22 int bin[N];
     23 int num[N];;
     24 int root[N];
     25 void pushup(int rt)
     26 {
     27     tr[rt].wgt=tr[rt].num+tr[tr[rt].ls].wgt+tr[tr[rt].rs].wgt;
     28     return ;
     29 }
     30 int newp(void)
     31 {
     32     if(top)
     33         return bin[top--];
     34     return ++siz;
     35 }
     36 void apply(int &rt)
     37 {
     38     rt=newp();
     39     tr[rt]=stdtrent;
     40     tr[rt].rnd=rand();
     41     tr[rt].num=1;
     42     return ;
     43 }
     44 void Del(int spc)
     45 {
     46     bin[++top]=spc;
     47     return ;
     48 }
     49 void lturn(int &rt)
     50 {
     51     int tmp=tr[rt].ls;
     52     tr[rt].ls=tr[tmp].rs;
     53     tr[tmp].rs=rt;
     54     pushup(rt);
     55     rt=tmp;
     56     pushup(rt);
     57     return ;
     58 }
     59 void rturn(int &rt)
     60 {
     61     int tmp=tr[rt].rs;
     62     tr[rt].rs=tr[tmp].ls;
     63     tr[tmp].ls=rt;
     64     pushup(rt);
     65     rt=tmp;
     66     pushup(rt);
     67     return ;
     68 }
     69 void Insert(int &rt,int v)
     70 {
     71     if(!rt)
     72     {
     73         apply(rt);
     74         tr[rt].val=v;
     75         pushup(rt);
     76         return ;
     77     }
     78     if(tr[rt].val==v)
     79     {
     80         tr[rt].num++;
     81     }else if(tr[rt].val>v)
     82     {
     83         Insert(tr[rt].ls,v);
     84         if(tr[tr[rt].ls].rnd<tr[rt].rnd)
     85             lturn(rt);
     86     }else{
     87         Insert(tr[rt].rs,v);
     88         if(tr[tr[rt].rs].rnd<tr[rt].rnd)
     89             rturn(rt);
     90     }
     91     pushup(rt);
     92     return ;
     93 }
     94 void Delete(int &rt,int v)
     95 {
     96     if(!rt)
     97         return ;
     98     if(tr[rt].val==v)
     99     {
    100         if(tr[rt].num>1)
    101             tr[rt].num--;
    102         else{
    103             if(!tr[rt].ls||!tr[rt].rs)
    104             {
    105                 Del(rt);
    106                 rt=tr[rt].ls|tr[rt].rs;
    107                 return ;
    108             }else if(tr[tr[rt].ls].rnd<tr[tr[rt].rs].rnd)
    109             {
    110                 lturn(rt);
    111                 Delete(tr[rt].rs,v);
    112             }else{
    113                 rturn(rt);
    114                 Delete(tr[rt].ls,v);
    115             }
    116         }
    117     }else if(tr[rt].val>v)
    118         Delete(tr[rt].ls,v);
    119     else
    120         Delete(tr[rt].rs,v);
    121     pushup(rt);
    122     return ;
    123 }
    124 int Rank(int rt,int v)
    125 {
    126     if(!rt)
    127         return 0;
    128     if(tr[rt].val==v)
    129         return tr[tr[rt].ls].wgt;
    130     if(tr[rt].val>v)
    131         return Rank(tr[rt].ls,v);
    132     return Rank(tr[rt].rs,v)+tr[rt].num+tr[tr[rt].ls].wgt;
    133 }
    134 void Getpre(int rt,int v)
    135 {
    136     if(!rt)
    137         return ;
    138     if(tr[rt].val<v)
    139     {
    140         ans=std::max(ans,tr[rt].val);
    141         Getpre(tr[rt].rs,v);
    142     }else
    143         Getpre(tr[rt].ls,v);
    144     return ;
    145 }
    146 void Getnxt(int rt,int v)
    147 {
    148     if(!rt)
    149         return ;
    150     if(tr[rt].val>v)
    151     {
    152         ans=std::min(ans,tr[rt].val);
    153         Getnxt(tr[rt].ls,v);
    154     }else
    155         Getnxt(tr[rt].rs,v);
    156     return ;
    157 }
    158 void Build(int l,int r,int spc)
    159 {
    160     for(int i=l;i<=r;i++)
    161         Insert(root[spc],num[i]);
    162     if(l==r)
    163         return ;
    164     int mid=(l+r)>>1;
    165     Build(l,mid,lll);
    166     Build(mid+1,r,rrr);
    167     return ;
    168 }
    169 int rank(int l,int r,int spc,int ll,int rr,int v)
    170 {
    171     if(ll>r||l>rr)
    172         return 0;
    173     if(ll<=l&&r<=rr)
    174         return Rank(root[spc],v);
    175     int mid=(l+r)>>1;
    176     return rank(l,mid,lll,ll,rr,v)+rank(mid+1,r,rrr,ll,rr,v);
    177 }
    178 void update(int l,int r,int spc,int pos,int v,bool add)
    179 {
    180     if(add)
    181         Insert(root[spc],v);
    182     else
    183         Delete(root[spc],v);
    184     if(l==r)
    185         return ;
    186     int mid=(l+r)>>1;
    187     if(pos<=mid)
    188         update(l,mid,lll,pos,v,add);
    189     else
    190         update(mid+1,r,rrr,pos,v,add);
    191     return ;
    192 }
    193 void getpre(int l,int r,int spc,int ll,int rr,int v)
    194 {
    195     if(l>rr||ll>r)
    196         return ;
    197     if(ll<=l&&r<=rr)
    198     {
    199         Getpre(root[spc],v);
    200         return ;
    201     }
    202     int mid=(l+r)>>1;
    203     getpre(l,mid,lll,ll,rr,v);
    204     getpre(mid+1,r,rrr,ll,rr,v);
    205     return ;
    206 }
    207 void getnxt(int l,int r,int spc,int ll,int rr,int v)
    208 {
    209     if(l>rr||ll>r)
    210         return ;
    211     if(ll<=l&&r<=rr)
    212     {
    213         Getnxt(root[spc],v);
    214         return ;
    215     }
    216     int mid=(l+r)>>1;
    217     getnxt(l,mid,lll,ll,rr,v);
    218     getnxt(mid+1,r,rrr,ll,rr,v);
    219     return ;
    220 }
    221 int main()
    222 {
    223     scanf("%d%d",&n,&m);
    224     for(int i=1;i<=n;i++)
    225         scanf("%d",&num[i]);
    226     Build(1,n,1);
    227     while(m--)
    228     {
    229         int cmd;
    230         scanf("%d",&cmd);
    231         if(cmd==1)
    232         {
    233             int l,r,x;
    234             scanf("%d%d%d",&l,&r,&x);
    235             ans=rank(1,n,1,l,r,x)+1;
    236             printf("%d
    ",ans);
    237         }else if(cmd==2)
    238         {
    239             int ll,rr,k;
    240             scanf("%d%d%d",&ll,&rr,&k);
    241             int l=-oo,r=oo;
    242             while(l<=r)
    243             {
    244                 int mid=(l+r)>>1;
    245                 if(rank(1,n,1,ll,rr,mid)<k)
    246                 {
    247                     ans=mid;
    248                     l=mid+1;
    249                 }else
    250                     r=mid-1;
    251             }
    252             printf("%d
    ",ans);
    253         }else if(cmd==3)
    254         {
    255             int pos,newv;
    256             scanf("%d%d",&pos,&newv);
    257             update(1,n,1,pos,num[pos],0);
    258             num[pos]=newv;
    259             update(1,n,1,pos,num[pos],1);
    260         }else if(cmd==4)
    261         {
    262             int l,r,x;
    263             scanf("%d%d%d",&l,&r,&x);
    264             ans=-2147483647;
    265             getpre(1,n,1,l,r,x);
    266             printf("%d
    ",ans);
    267         }else{
    268             int l,r,x;
    269             scanf("%d%d%d",&l,&r,&x);
    270             ans=2147483647;
    271             getnxt(1,n,1,l,r,x);
    272             printf("%d
    ",ans);
    273         }
    274     }
    275     return 0;
    276 }
  • 相关阅读:
    sql中的exists用法
    采用spring的schedule注解配置定时任务
    java通过传入的日期,获取所在周的周一至周日
    forever start app.js 启动node时,服务访问一次后第二次就不能访问了
    linux 安装nginx
    linux 常用命令
    8位字节表示的有符号数范围是-128~127
    极光推送免费版
    tomcat 设置连接数
    查看linux内存使用情况
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10116135.html
Copyright © 2011-2022 走看看