可持久化树模板

您需要维护一个序列,其中需要提供以下操作:

  1. 插入一个数到序列的第 t 版本使其成为序列的第 k 项,这个数为 x ;

  2. 删除序列的第 t 版本的第 k 项;

  3. 查询序列的第 t 版本的第 k 项。

第 0 个版本为空序列。修改操作不会影响被修改的版本,而总是产生一个新版本。

Input

第一行有一个正整数 n 表示操作的数量。

接下来 n 行每行第一个正整数 opt 表示操作的类型,后面有 3 个整数 t,k,x 或 2 个整数 t,k 表示操作的参数。

1 ≤ n ≤ 3×105 , 1 ≤ opt ≤ 3  ,  0 ≤ x < 109 ,保证所有操作合法。

由于数据量较大,可能需要使用特别的读入方式。

Output

对于每个查询操作输出一行一个数,表示查询的结果。

Sample Input

17
1 0 1 1
1 1 1 2
1 2 1 3
2 3 2
3 4 2
1 4 3 4
1 5 1 5
3 3 2
1 3 4 6
1 6 3 7
1 7 1 8
3 8 2
3 7 3
2 8 4
2 9 2
3 11 4
3 10 4

Sample Output

1
2
3
1
6
4

Hint

每次操作后的序列如下

1 | 1
2 | 2 1
3 | 3 2 1
4 | 3 1
(=> 1)
5 | 3 1 4
6 | 5 3 1 4
(=> 2)
7 | 3 2 1 6
8 | 5 3 7 1 4
9 | 8 3 2 1 6
(=> 3)
(=> 1)
10 | 5 3 7 4
11 | 8 2 1 6
(=> 6)
(=> 4)

 
//Splay Tree
#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;

/*
rope
rope(rope&); //构造函数、传入rope可以用来拷贝
push_back(x); // 在末尾添加x
insert(pos, x); // 在pos插入x
erase(pos, x); // 从pos开始删除x个
copy(pos, len, x); // 从pos开始到pos+len为止用x代替
replace(pos, x); // 从pos开始换成x
substr(pos, x); // 提取pos开始x个
at(x) / [x]; // 访问第x个元素
时间复杂度为n*(n^0.5)
*/

#include <ext/rope>
using namespace __gnu_cxx;
const int maxn = 3e5 + 10;

int n, id;
rope<int> * Rope[maxn];

int main(void){__stTIME();__IOPUT();

    int n;
    sci(n);

    Rope[0] = new rope<int>();

    while(n--){
        int op, t, k, x;
        sciii(op, t, k);
        if(op == 1){
            sci(x);
            Rope[++id] = new rope<int>(*Rope[t]);
            Rope[id]->insert(k - 1, x);
        }
        if(op == 2){
            Rope[++id] = new rope<int>(*Rope[t]);
            Rope[id]->erase(k - 1, 1);
        }
        if(op == 3) printf("%d
", Rope[t]->at(k-1));
    }



__enTIME();return 0;}


void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}
View Code
原文地址:https://www.cnblogs.com/shuaihui520/p/9756113.html