zoukankan      html  css  js  c++  java
  • 【模板】可持久化平衡树

    题目背景

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

    数据已经经过强化

    感谢@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 < i0vi<i ),optiopt_iopti 表示操作的序号( 1≤opt≤6 1 leq opt leq 6 1opt6 ), 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 1n10

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

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

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

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

    对于100%的数据满足: 1≤n≤5⋅105 1 leq n leq 5cdot {10}^5 1n5105 , −109≤xi≤109-{10}^9 leq x_i leq {10}^9109xi109

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

    样例说明:

    共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
    ", kth(rot[i], w));
    		else if (f == 4)printf("%d
    ", getval(rot[i], w));
    		else if (f == 5)printf("%d
    ", getpre(rot[i], w));
    		else printf("%d
    ", nxt(rot[i], w));
    	}
    	return 0;
    }
    
    EPFL - Fighting
  • 相关阅读:
    Linux常用命令
    git常用命令查询
    专有名词
    dos2unix 转换字符
    常见脚本语言
    使用shell脚本自动化部署rabbitmp
    通过脚本来执行ssh登录
    码率mbps
    centos7 firewall指定IP与端口访问(常用)
    ubuntu16.04离线安装docker记录
  • 原文地址:https://www.cnblogs.com/zxyqzy/p/10346268.html
Copyright © 2011-2022 走看看