P3369 【模板】普通平衡树FHQtreap

P3369 【模板】普通平衡树(Treap/SBT)

题目描述

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

  1. 插入x数
  2. 删除x数(若有多个相同的数,因只删除一个)
  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
  4. 查询排名为x的数
  5. 求x的前驱(前驱定义为小于x,且最大的数)
  6. 求x的后继(后继定义为大于x,且最小的数)

输入输出格式

输入格式:

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

输出格式:

对于操作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 \leq 100000n≤100000

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

来源:Tyvj1728 原名:普通平衡树

在此鸣谢

code

 1 #include<cstdio>
 2 #include<algorithm>
 3
 4 using namespace std;
 5
 6 const int N = 500100;
 7 int ch[N][2],siz[N],key[N],val[N];
 8 int tn,Root;
 9
10 inline char nc() {
11     static char buf[100000],*p1 = buf,*p2 = buf;
12     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2) ? EOF : *p1++;
13 }
14 inline int read() {
15     int x = 0,f = 1;char ch = getchar();
16     for (; ch<‘0‘||ch>‘9‘; ch = getchar())
17         if (ch==‘-‘) f = -1;
18     for (; ch>=‘0‘&&ch<=‘9‘; ch = getchar())
19         x = x*10+ch-‘0‘;
20     return x * f;
21 }
22 inline void pushup(int x) {
23     siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
24 }
25 inline int makenode(int x) {
26     ++tn;val[tn] = x;siz[tn] = 1;key[tn] = rand();return tn;
27 }
28
29 int Merge(int x,int y) {
30     if (!x || !y) return x + y;
31     if (key[x] < key[y]) {
32         ch[x][1] = Merge(ch[x][1],y);
33         pushup(x); return x;
34     }
35     else {
36         ch[y][0] = Merge(x,ch[y][0]);
37         pushup(y); return y;
38     }
39 }
40 void Split(int now,int k,int &x,int &y) {
41     if (!now) x = y = 0;
42     else {
43         if (val[now] <= k)
44             x = now,Split(ch[now][1],k,ch[now][1],y);
45         else
46             y = now,Split(ch[now][0],k,x,ch[now][0]);
47         pushup(now);
48     }
49 }
50 inline int getkth(int p,int k) {
51     while (true) {
52         if (k == siz[ch[p][0]] + 1) return p;
53         if (ch[p][0] && k <= siz[ch[p][0]]) p = ch[p][0];
54         else k-= ((ch[p][0] ? siz[ch[p][0]] : 0) + 1),p = ch[p][1];
55     }
56 }
57 int main() {
58     int x,y,z,opt,k,n = read();
59     while (n--) {
60         opt = read(),k = read();
61         if (opt==1) {
62             Split(Root,k,x,y);
63             Root = Merge(Merge(x,makenode(k)),y);
64         }
65         else if (opt==2) {
66             Split(Root,k,x,y);
67             Split(x,k-1,x,z);
68             z = Merge(ch[z][0],ch[z][1]);
69             Root = Merge(Merge(x,z),y);
70         }
71         else if (opt==3) {
72             Split(Root,k-1,x,y);
73             printf("%d\n",siz[x]+1);
74             Root = Merge(x,y);
75         }
76         else if (opt==4)
77             printf("%d\n",val[getkth(Root,k)]);
78         else if (opt==5) {
79             Split(Root,k-1,x,y);
80             printf("%d\n",val[getkth(x,siz[x])]);
81             Root = Merge(x,y);
82         }
83         else {
84             Split(Root,k,x,y);
85             printf("%d\n",val[getkth(y,1)]);
86             Root = Merge(x,y);
87         }
88     }
89     return 0;
90 }
时间: 2024-10-19 00:31:44

P3369 【模板】普通平衡树FHQtreap的相关文章

luoguP3369[模板]普通平衡树(Treap/SBT) 题解

链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> #include<ctime> #include<queue> #incl

平衡树 fhqTreap 区间操作

//Treap fhq版(不旋转) //此模板为平衡树维护区间操作的模板 //注:在区间操作中split()标准变为子树大小 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<queue> #define INF 0x3f3f3f3f #de

模板 普通平衡树

Treap 版: 查询操作是最简单的,就是二叉搜索树.左旋右旋画一画就好了. 最近代码能力下降,码一码模板QAQ 1 #include<ctime> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 using namespace std; 7 struct pnt{ 8 int val; 9 int l; 10 int r; 11

模板 文艺平衡树

Splay模板,学完觉得比Treap简单,不过均摊的logn不能可持久化. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ls ch[0] 5 #define rs ch[1] 6 struct trnt{ 7 int ch[2]; 8 int chd; 9 int wgt; 10 int fa; 11 int v; 12 }tr[10000000]; 13 int root

【洛谷P3369】普通平衡树(splay)

emmmmm直接丢代码了 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<set> #include<map> #include<queue> #include<algorithm> #include<vector> #include<cstdlib> #include<

平衡树 fhqTreap

//Treap fhq版(不旋转) //所有操作依靠split()(分离)和merge()(合并)完成 //可支持区间操作和可持久化 比普通Treap更通用 //所有Treap中序遍历均为递增序列 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<

平衡树解析

转自:yyb巨佬的平衡树 不知道splay是啥,,你也要知道平衡树是啥... 平衡树是一个神奇的数据结构, 对于任意一个节点,左儿子的值比它小,右儿子的值比它大 并且任意一棵子树单独拎出来也是一棵平衡树 就像这样.... 各位大佬请原谅我丑陋无比的图 上面这个丑陋的东西就是一棵平衡树,他现在很平衡,是一棵满二叉树,高度正好是logn... 但是.. 如果这个丑陋的东西极端一点,他就会变成这样... 这张图依然很丑 现在看起来,这个东西一点都不平衡... 二叉树退化成了一条链 如果要查询的话,,,

算法学习:伸展树(splay)

[定义] [平衡树] 每个叶子结点的深度差不超过1的二叉树 [伸展树] [常用问题] splay的操作,通过左旋右旋,将某个结点通过旋转旋转至根节点,使树的结构发生变化,尽可能的平衡 并且因为左旋右旋的性质,当原树是一个二叉排序树的时候,splay依旧能够使原树保持二叉排序树的性质 左旋右旋图片 [模板题] [luogu P3369]普通平衡树 [题意]实现一颗二叉排序树的增删查改 [注]对数据结构的理解见注释 [代码] #include<cstdio> #include<iostrea

数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) #include <cstdio> #define Max 100005 #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) Inline void read (int &now) { now = 0; register char word = getchar (); bool temp = false; while (wor