• [luogu 3369]普通平衡树(fhq_treap)


    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    1. 插入x数

    2. 删除x数(若有多个相同的数,因只删除一个)

    3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

    4. 查询排名为x的数

    5. 求x的前驱(前驱定义为小于x,且最大的数)

    6. 求x的后继(后继定义为大于x,且最小的数)

    输入输出格式

    输入格式:

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1≤opt≤6 1 leq opt leq 6 1opt6 )

    输出格式:

    对于操作3,4,5,6每行输出一个数,表示对应答案

    输入输出样例

    输入样例#1: 复制
    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598
    输出样例#1: 复制
    106465
    84185
    492737

    说明

    时空限制:1000ms,128M

    1.n的数据范围: n≤100000 n leq 100000 n100000

    2.每个数的数据范围: $[-{10}^7, {10}^7]$

    题解:

    模板题,用的是fhq_treap。

     1 //Never forget why you start
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<cmath>
     7 #include<algorithm>
     8 #include<ctime>
     9 #define ll(x) tre[x].child[0]
    10 #define rr(x) tre[x].child[1]
    11 #define son(x,t) tre[x].child[t]
    12 using namespace std;
    13 int n,m,cnt,root;
    14 struct Treap{
    15   int child[2],x,size,rev;
    16 }tre[100005];
    17 void push_up(int root){
    18   tre[root].size=tre[ll(root)].size+tre[rr(root)].size+1;
    19 }
    20 int newnode(int x){
    21   cnt++;
    22   tre[cnt].size=1;
    23   tre[cnt].rev=rand();
    24   tre[cnt].x=x;
    25   return cnt;
    26 }
    27 void split(int now,int k,int &x,int &y){
    28   if(!now)x=y=0;
    29   else{
    30     if(tre[now].x<=k)
    31       x=now,split(rr(now),k,rr(now),y);
    32     else
    33       y=now,split(ll(now),k,x,ll(now));
    34     push_up(now);
    35   }
    36 }
    37 int merge(int x,int y){
    38   if(!x||!y)return x+y;
    39   if(tre[x].rev<tre[y].rev){
    40     rr(x)=merge(rr(x),y);
    41     push_up(x);
    42     return x;
    43   }
    44   else{
    45     ll(y)=merge(x,ll(y));
    46     push_up(y);
    47     return y;
    48   }
    49 }
    50 int find(int root,int k){
    51   int y=tre[ll(root)].size;
    52   if(y+1==k)return root;
    53   else if(y>=k)return find(ll(root),k);
    54   else find(rr(root),k-y-1);
    55 }
    56 int main(){
    57   int i,j,a,b,c;
    58   srand(time(0));
    59   scanf("%d",&n);
    60   while(n--){
    61     scanf("%d%d",&i,&j);
    62     if(i==1){
    63       split(root,j,a,b);
    64       root=merge(merge(a,newnode(j)),b);
    65     }
    66     if(i==2){
    67       split(root,j,a,c);
    68       split(a,j-1,a,b);
    69       b=merge(ll(b),rr(b));
    70       root=merge(merge(a,b),c);
    71     }
    72     if(i==3){
    73       split(root,j-1,a,b);
    74       printf("%d
    ",tre[a].size+1);
    75       root=merge(a,b);
    76     }
    77     if(i==4){
    78       printf("%d
    ",tre[find(root,j)].x);
    79     }
    80     if(i==5){
    81       split(root,j-1,a,b);
    82       printf("%d
    ",tre[find(a,tre[a].size)].x);
    83       root=merge(a,b);
    84     }
    85     if(i==6){
    86       split(root,j,a,b);
    87       printf("%d
    ",tre[find(b,1)].x);
    88       root=merge(a,b);
    89     }
    90   }
    91   return 0;
    92 }
  • 相关阅读:
    【Programming Clip】位运算的应用
    【Linux实用技术】LFS6.3构建实录
    【嵌入式开发技术之环境配置】Ubuntu下 TFTP服务的配置
    IIS上注册.Net
    C#高效分页代码(不用存储过程)
    OpenDataSOurce 指定参数
    存储过程中while循环
    SQL语句中的判断(条件语句)
    C#.NET支付宝接口
    局域网共享访问要密码 局域网访问需要密码 访问网上邻居需要密码 局域网不能共享 windows xp共享
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/8278612.html
Copyright © 2020-2023  润新知