Bzoj3224普通平衡树

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

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

Output

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

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

1.n的数据范围:n<=100000

2.每个数的数据范围:[-1e7,1e7]

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstdlib>
  5 using namespace std;
  6 const int MAXN=1000001;
  7 const int INF=1e9;
  8 struct Treap
  9 {
 10     int ch[2],key,tms,size,dat;
 11 }treap[MAXN];
 12 int root,tot;
 13 int T,op,n;
 14 inline int cmp(int x,int tar)
 15 {
 16     if(tar==treap[x].dat) return -1;
 17     return (tar<treap[x].dat?0:1);
 18 }
 19 inline void maintain(int x)
 20 {
 21     treap[x].size=treap[x].tms;
 22     if(treap[x].ch[0]) treap[x].size+=treap[treap[x].ch[0]].size;
 23     if(treap[x].ch[1]) treap[x].size+=treap[treap[x].ch[1]].size;
 24 }
 25 inline void rotate(int &x,int d)
 26 {
 27     int p=treap[x].ch[d^1];
 28     treap[x].ch[d^1]=treap[p].ch[d];
 29     treap[p].ch[d]=x;
 30     maintain(x);
 31     maintain(p);
 32     x=p;
 33 }
 34 void ins(int &x,int tar)
 35 {
 36     if(!x)
 37     {
 38         tot++;
 39         treap[tot].key=rand();
 40         treap[tot].dat=tar;
 41         treap[tot].tms=1;
 42         treap[tot].size=1;
 43         x=tot;
 44         return;
 45     }
 46     int d=cmp(x,tar);
 47     if(d==-1) treap[x].tms++;
 48     else
 49     {
 50         ins(treap[x].ch[d],tar);
 51         if(treap[treap[x].ch[d]].key>treap[x].key) rotate(x,d^1);
 52     }
 53     maintain(x);
 54 }
 55 void del(int &x,int tar)
 56 {
 57     int d=cmp(x,tar);
 58     if(d==-1)
 59     {
 60         if(treap[x].tms>1) treap[x].tms--;
 61         else
 62         {
 63             if(!treap[x].ch[0]&&!treap[x].ch[1]) x=0;
 64             else if(!treap[x].ch[0]&&treap[x].ch[1]) x=treap[x].ch[1];
 65             else if(treap[x].ch[0]&&!treap[x].ch[1]) x=treap[x].ch[0];
 66             else
 67             {
 68                 int t=(treap[treap[x].ch[0]].key>treap[treap[x].ch[1]].key?1:0);
 69                 rotate(x,t);
 70                 del(treap[x].ch[t],tar);
 71             }
 72         }
 73     }
 74     else del(treap[x].ch[d],tar);
 75     maintain(x);
 76 }
 77 inline int GetPre(int x,int tar)
 78 {
 79     int con=-INF;
 80     while(x)
 81     {
 82         int d=cmp(x,tar);
 83         if(d==-1) x=treap[x].ch[0];
 84         else if(d)
 85         {
 86             con=max(con,treap[x].dat);
 87             x=treap[x].ch[1];
 88         }
 89         else x=treap[x].ch[0];
 90     }
 91     return con;
 92 }
 93 inline int GetNext(int x,int tar)
 94 {
 95     int con=INF;
 96     while(x)
 97     {
 98         int d=cmp(x,tar);
 99         if(d==-1) x=treap[x].ch[1];
100         else if(d) x=treap[x].ch[1];
101         else
102         {
103             con=min(con,treap[x].dat);
104             x=treap[x].ch[0];
105         }
106     }
107     return con;
108 }
109 int GetRank(int x,int tar)
110 {
111     int d=cmp(x,tar);
112     if(d==-1) return treap[treap[x].ch[0]].size+1;
113     else if(d) return treap[treap[x].ch[0]].size+treap[x].tms+GetRank(treap[x].ch[1],tar);
114     else return GetRank(treap[x].ch[0],tar);
115 }
116 int GetKth(int x,int k)
117 {
118     if(k<=treap[treap[x].ch[0]].size) return GetKth(treap[x].ch[0],k);
119     k-=treap[treap[x].ch[0]].size+treap[x].tms;
120     if(k<=0) return treap[x].dat;
121     else return GetKth(treap[x].ch[1],k);
122 }
123 int main(int argc, char *argv[])
124 {
125     scanf("%d",&T);
126     for(int i=1;i<=T;i++)
127     {
128         scanf("%d%d",&op,&n);
129         if(op==1) ins(root,n);
130         else if(op==2) del(root,n);
131         else if(op==3) printf("%d\n",GetRank(root,n));
132         else if(op==4) printf("%d\n",GetKth(root,n));
133         else if(op==5) printf("%d\n",GetPre(root,n));
134         else if(op==6) printf("%d\n",GetNext(root,n));
135     }
136     return 0;
137 }
时间: 2024-10-13 15:53:49

Bzoj3224普通平衡树的相关文章

[BZOJ3224]普通平衡树(旋转treap)

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 20328  Solved: 8979[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

bzoj3224 普通平衡树(splay 模板)

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 11427  Solved: 4878[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为

[TYVJ1728/BZOJ3224]普通平衡树-替罪羊树

Problem 普通平衡树 Solution 本题是裸的二叉平衡树.有很多种方法可以实现.这里打的是替罪羊树模板. 此题极其恶心. 前驱后继模块需要利用到rank模块来换一种思路求. 很多细节的地方容易炸.我拿数据调了很久才A. (delt()删除模块其实是不需要重建的,不影响时间复杂度) 替罪羊树具体详见此篇知乎:替罪羊树 AC Code 1 #include "iostream" 2 #include "cstdio" 3 #define alpha 0.7 4

[您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我们还是用rand()来实现平衡 而无旋treap与treap不同的地方,也是其核心,就是它不旋转用两个新的核心函数:merge函数(合并两棵子树)和split函数(分裂出某棵树的前k个节点,并且作为一棵树返回) 首先看merge函数,它是一个递归实现的过程,先看代码: 1 Treap *merge(

bzoj3224 普通平衡树

Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) Input 第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6) Output 对于操作3,4,5,6每行输

[bzoj3224]普通平衡树[Treap]

Treap 的各种操作,模板题,要再写几遍 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 9 using namespace std; 10 11 class Treap 12

bzoj3224 普通平衡树 splay模板

题目传送门 题目大意:完成一颗splay树. 思路:模板题,学着还是很有意思的. 学习splay树:蒟蒻yyb 该题模板:汪立超 #include<bits/stdc++.h> #define CLR(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; int root,N=0,n,p,q; int fa[100001],c[100001][2],size[100001],sp[100001]; void

【转】 史上最详尽的平衡树(splay)讲解与模板(非指针版spaly)

ORZ原创Clove学姐: 变量声明:f[i]表示i的父结点,ch[i][0]表示i的左儿子,ch[i][1]表示i的右儿子,key[i]表示i的关键字(即结点i代表的那个数字),cnt[i]表示i结点的关键字出现的次数(相当于权值),size[i]表示包括i的这个子树的大小:sz为整棵树的大小,root为整棵树的根. 再介绍几个基本操作: [clear操作]:将当前点的各项值都清0(用于删除之后) inline void clear(int x){ ch[x][0]=ch[x][1]=f[x]

平衡树讲解(旋转treap,非旋转treap,splay)

在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用的:treap和splay(其中treap包括旋转treap和非旋转treap). 一.treap treap这个词是由tree和heap组合而成,意思是树上的的堆(其实就是字面意思啦qwq).treap可以说是由二叉搜索树(BST)进化而来,二叉搜索树每个点满足它左子树中所有点权值都比它小,它右子