【模板】可持久化平衡树

题目背景

本题为题目 普通平衡树 的可持久化加强版。

数据已经经过强化

感谢@Kelin 提供的一组hack数据

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):

  1. 插入x数
  2. 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)
  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
  4. 查询排名为x的数
  5. 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)
  6. 求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)

和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本。(操作3, 4, 5, 6即保持原版本无变化)

每个版本的编号即为操作的序号(版本0即为初始状态,空树)

输入输出格式

输入格式:

第一行包含一个正整数N,表示操作的总数。

接下来每行包含三个整数,第 iii 行记为 vi,opti,xiv_i, opt_i, x_ivi?,opti?,xi?。

viv_ivi?表示基于的过去版本号( 0≤vi<i 0 \leq v_i < i0≤vi?<i ),optiopt_iopti? 表示操作的序号( 1≤opt≤6 1 \leq opt \leq 6 1≤opt≤6 ), xix_ixi? 表示参与操作的数值

输出格式:

每行包含一个正整数,依次为各个3,4,5,6操作所对应的答案

输入输出样例

输入样例#1:
复制

10
0 1 9
1 1 3
1 1 10
2 4 2
3 3 9
3 1 2
6 4 1
6 2 9
8 6 3
4 5 8

输出样例#1: 复制

9
1
2
10
3

说明

数据范围:

对于28%的数据满足: 1≤n≤10 1 \leq n \leq 10 1≤n≤10

对于44%的数据满足: 1≤n≤2?102 1 \leq n \leq 2\cdot {10}^2 1≤n≤2?102

对于60%的数据满足: 1≤n≤3?103 1 \leq n \leq 3\cdot {10}^3 1≤n≤3?103

对于84%的数据满足: 1≤n≤105 1 \leq n \leq {10}^5 1≤n≤105

对于92%的数据满足: 1≤n≤2?105 1 \leq n \leq 2\cdot {10}^5 1≤n≤2?105

对于100%的数据满足: 1≤n≤5?105 1 \leq n \leq 5\cdot {10}^5 1≤n≤5?105 , ?109≤xi≤109-{10}^9 \leq x_i \leq {10}^9?109≤xi?≤109

经实测,正常常数的可持久化平衡树均可通过,请各位放心

样例说明:

共10次操作,11个版本,各版本的状况依次是:

  1. [][][]
  2. [9][9][9]
  3. [3,9][3, 9][3,9]
  4. [9,10][9, 10][9,10]
  5. [3,9][3, 9][3,9]
  6. [9,10][9, 10][9,10]
  7. [2,9,10][2, 9, 10][2,9,10]
  8. [2,9,10][2, 9, 10][2,9,10]
  9. [2,10][2, 10][2,10]
  10. [2,10][2, 10][2,10]
  11. [3,9][3, 9][3,9]

FHQ Treap;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 200005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-5
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii;

inline int rd() {
	int x = 0;
	char c = getchar();
	bool f = false;
	while (!isdigit(c)) {
		if (c == ‘-‘) f = true;
		c = getchar();
	}
	while (isdigit(c)) {
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	return f ? -x : x;
}

ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a%b);
}
int sqr(int x) { return x * x; }

/*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
	if (!b) {
		x = 1; y = 0; return a;
	}
	ans = exgcd(b, a%b, x, y);
	ll t = x; x = y; y = t - a / b * y;
	return ans;
}
*/

struct node {
	int l, r;
	int siz;
	int rnd;
	int v;
}t[500005*50];
int cnt, rot[500005];
void upd(int k) {
	t[k].siz = t[t[k].l].siz + t[t[k].r].siz + 1;
}

void newnode(int &k, int x) {
	t[k = ++cnt].v = x; t[k].siz = 1; t[k].rnd = rand();
}
int merge(int a, int b) {
	if (!a || !b)return a + b;
	if (t[a].rnd > t[b].rnd) {
		int p = ++cnt; t[p] = t[a];
		t[p].r = merge(t[p].r, b);
		upd(p); return p;
	}
	else {
		int p = ++cnt; t[p] = t[b];
		t[p].l = merge(a, t[p].l);
		upd(p); return p;
	}
}
void split(int now, int  k, int &x, int &y) {
	if (!now)x = y = 0;
	else {
		if (t[now].v <= k) {
			x = ++cnt; t[x] = t[now];
			split(t[x].r, k, t[x].r, y);
			upd(x);
		}
		else {
			y = ++cnt; t[y] = t[now];
			split(t[y].l, k, x, t[y].l);
			upd(y);
		}
	}
}

void del(int &rt, int w) {
	int x = 0, y = 0, z = 0;
	split(rt, w, x, z); split(x, w - 1, x, y);
	y = merge(t[y].l, t[y].r);
	rt = merge(merge(x, y), z);
}

void ins(int &rt, int w) {
	int x = 0, y = 0, z = 0;
	split(rt, w, x, y); newnode(z, w);
	rt = merge(merge(x, z), y);
}

int getval(int k, int w) {
	if (w == t[t[k].l].siz + 1)return t[k].v;
	else if (w <= t[t[k].l].siz)return getval(t[k].l, w);
	else return getval(t[k].r, w - t[t[k].l].siz - 1);
}
int kth(int &rt, int w) {
	int x, y;
	split(rt, w - 1, x, y);
	int ans = t[x].siz + 1;
	rt = merge(x, y);
	return ans;
}

int getpre(int rt, int w) {
	int x, y, k, ans;
	split(rt, w - 1, x, y);
	if (!x)return -inf;
	k = t[x].siz;
	ans = getval(x, k);
	rt = merge(x, y); return ans;
}
int nxt(int rt, int w) {
	int x, y, ans;
	split(rt, w, x, y);
	if (!y)return inf;
	else ans = getval(y, 1);
	rt = merge(x, y); return ans;
}

int main()
{
	//ios::sync_with_stdio(0);
	int n, f, w, tm; n = rd();
	for (int i = 1; i <= n; i++) {
		tm = rd(); f = rd(); w = rd();
		rot[i] = rot[tm];
		if (f == 1)ins(rot[i], w);
		else if (f == 2)del(rot[i], w);
		else if (f == 3)printf("%d\n", kth(rot[i], w));
		else if (f == 4)printf("%d\n", getval(rot[i], w));
		else if (f == 5)printf("%d\n", getpre(rot[i], w));
		else printf("%d\n", nxt(rot[i], w));
	}
	return 0;
}

原文地址:https://www.cnblogs.com/zxyqzy/p/10346268.html

时间: 2024-10-25 20:26:56

【模板】可持久化平衡树的相关文章

luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树)(主席树)

luogu P3919 [模板]可持久化数组(可持久化线段树/平衡树) 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<iomanip> #include<algorithm> #include<ctime> #include<queue> #inc

Luogu P3835 【模板】可持久化平衡树

P3835 [模板]可持久化平衡树 题意 题目背景 本题为题目普通平衡树的可持久化加强版. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本): 插入\(x\)数 删除\(x\)数(若有多个相同的数,因只删除一个,如果没有请忽略该操作) 查询\(x\)数的排名(排名定义为比当前数小的数的个数\(+1\).若有多个相同的数,因输出最小的排名) 查询排名为x的数 求\(x\)的前驱(前驱定义为小于\(x\),且最大的数,如不存在输出\(-2

洛谷P3835 【模板】可持久化平衡树

题目背景 本题为题目 普通平衡树 的可持久化加强版. 数据已经经过强化 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本): 插入x数 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作) 查询x数的排名(排名定义为比当前数小的数的个数+1.若有多个相同的数,因输出最小的排名) 查询排名为x的数 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647) 求x的后继(后继定义为大于x,且最小的数,如不存在

数组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

P3391 【模板】文艺平衡树(Splay)

题目背景 这是一道经典的Splay模板题--文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n?1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r

替罪羊树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 闲的没事,把各种平衡树都写写 比较比较... 下面是替罪羊树 #include <cstdio> #include <vector> #define Max_ 100010 #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) Inline void read (int &now) { register char w

[rope大法好] STL里面的可持久化平衡树--rope

简单用法: #include <ext/rope> using namespace __gnu_cxx; int a[1000]; rope<int> x; rope<int> x(a,a + n); rope<int> a(x); x->at(10); x[10]; x->push_back(x) // 在末尾添加x x->insert(pos,x) // 在pos插入x x->erase(pos,x) // 从pos开始删除x个

红黑树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)

二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 近几天闲来无事...就把各种平衡树都写了一下... 下面是红黑树(Red Black Tree) #include <cstdio> #define Max 100001 #define Red true #define Black false #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) Inline void read (i

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

二次联通门 : P3369 [模板]普通平衡树(Treap/SBT) /* luogu P3369 [模板]普通平衡树(Treap/SBT) splay 模板 支持插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(若有多个相同的数,因输出最小的排名) 查询排名为x的数 求x的前驱(前驱定义为小于x,且最大的数) 求x的后继(后继定义为大于x,且最小的数) */ #include <cstdio> #define Max 200005 void read (int &