【LG3835】可持久化平衡树

【LG3835】可持久化平衡树

题面

洛谷

解法一

参考文章

rope大法好

(rope)基本操作:

#include<ext/rope>
using namespace __gnu_cxx;//rope的命名空间
rope<type> R;
R.push_back(a) //往后插入
R.insert(pos,a)//在pos位置插入a,pos是一个迭代器。
R.erase(pos,n)//在pos位置删除n个元素。
R.replace(pos,x)//从pos开始替换成x
R.substr(pos,x)//从pos开始提取x个。
//多数时候定义rope用指针(方便可持久化) 所以上面的点多数时候要换成->

再配合二分即可实现各种操作

如何进行复制:

rope<type>* R[1000];
R[i] = new rope<type>(*R[v]);

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <ext/rope>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_cxx; 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (ch != '-' && (ch > '9' || ch < '0')) ch = getchar();
    if (ch == '-') w = -1 , ch = getchar();
    while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    return w * data;
} 
#define MAX_N 500005 
rope<int> *rop[MAX_N]; 
int N; 
int main () {  
    N = gi(); 
    rop[0] = new rope<int>(); 
    for (int i = 1; i <= N; i++) { 
    	int v = gi(), opt = gi(), x = gi(); 
    	rop[i] = new rope<int>(*rop[v]); 
    	if (opt == 1) rop[i]->insert(lower_bound(rop[i]->begin(), rop[i]->end(), x) - rop[i]->begin(), x); 
    	if (opt == 2) { 
    	    auto ite = lower_bound(rop[i]->begin(), rop[i]->end(), x); 
    	    if (ite != rop[i]->end() && *ite == x) rop[i]->erase(ite - rop[i]->begin(), 1); 
        } 
        if (opt == 3) 
        	printf("%d
", (int)(lower_bound(rop[i]->begin(), rop[i]->end(), x) - rop[i]->begin()) + 1); 
        if (opt == 4) printf("%d
", *(rop[i]->begin() + x - 1)); 
        if (opt == 5) { 
            auto ite = lower_bound(rop[i]->begin(), rop[i]->end(), x); 
            if (ite == rop[i]->begin() - 1) puts("-2147483647"); 
            else --ite, printf("%d
", *ite); 
        } 
        if (opt == 6) { 
            auto ite = upper_bound(rop[i]->begin(), rop[i]->end(), x); 
            if (ite == rop[i]->end()) puts("2147483647"); 
            printf("%d
", *ite); 
        } 
    } 
    return 0; 
} 

解法二

用可持久化(trie)可以很方便地实现

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
#include <climits> 
using namespace std;

inline int gi() {
	register int data = 0, w = 1;
	register char ch = 0;
	while (!isdigit(ch) && ch != '-') ch = getchar(); 
	if (ch == '-') w = -1, ch = getchar();
	while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
	return w * data; 
}

const int MAX_N = 5e5 + 5; 
const int T = 1e9; 
struct Trie { int ch[2], size; } t[MAX_N << 5]; 
int N, rt[MAX_N], tot;
bool find(int o, int v) {
	v += T; 
	for (int i = 31; ~i; i--) {
		int c = v >> i & 1;
		if (!t[o].size || !o) return 0; 
		o = t[o].ch[c]; 
	} 
	return 1; 
} 
void insert(int &x, int p, int v) {
	x = ++tot; int o = x; 
	v += T, t[o].size = t[p].size + 1; 
	for (int i = 31; ~i; i--) { 
		int c = v >> i & 1;
		t[o].ch[c ^ 1] = t[p].ch[c ^ 1]; 
		t[o].ch[c] = ++tot; 
		o = t[o].ch[c], p = t[p].ch[c]; 
		t[o].size = t[p].size + 1; 
	} 
} 
void erase(int &x, int p, int v) { 
	if (!find(p, v)) return (void)(x = p);
	x = ++tot; int o = x; 
	v += T, t[o].size = t[p].size - 1; 
	for (int i = 31; ~i; i--) {
		int c = v >> i & 1;
		t[o].ch[c ^ 1] = t[p].ch[c ^ 1]; 
		t[o].ch[c] = ++tot; 
		o = t[o].ch[c], p = t[p].ch[c]; 
		t[o].size = t[p].size - 1; 
	} 
} 
int Kth(int o, int k) { 
	long long res = -T; 
	for (int i = 31; ~i; i--) {
		int sz = t[t[o].ch[0]].size; 
		if (k <= sz) o = t[o].ch[0]; 
		else res += (1 << i), o = t[o].ch[1], k -= sz; 
	}
	return res; 
} 
int LR(int o, int v) { 
	v += T; int res = 0; 
	for (int i = 31; ~i; i--) { 
		int c = v >> i & 1; 
		if (c) res += t[t[o].ch[0]].size; 
		o = t[o].ch[c];
		if (!o || !t[o].size) return res; 
	} 
	return res; 
}
int UR(int o, int v) {
	v += T; int res = 0; 
	for (int i = 31; ~i; i--) { 
		int c = v >> i & 1; 
		if (!c) res += t[t[o].ch[1]].size; 
		o = t[o].ch[c];
		if (!o || !t[o].size) return res; 
	} 
	return res; 
} 
int Rnk(int o, int v) { return LR(o, v) + 1; } 

signed main () {
	N = gi(); 
	rt[0] = ++tot; 
	for (int i = 1; i <= N; i++) {
		int v = gi(), op = gi(), x = gi();
		if (op == 1) insert(rt[i], rt[v], x); 
		if (op == 2) erase(rt[i], rt[v], x); 
		if (op == 3) rt[i] = rt[v], printf("%d
", Rnk(rt[i], x));
		if (op == 4) rt[i] = rt[v], printf("%d
", Kth(rt[i], x));
		if (op == 5) {
			rt[i] = rt[v];
			int res = LR(rt[i], x);
			if (!res) printf("%d
", -INT_MAX);
			else printf("%d
", Kth(rt[i], res)); 
		}
		if (op == 6) {
			rt[i] = rt[v]; 
			int res = UR(rt[i], x);
			if (!res) printf("%d
", INT_MAX);
			else printf("%d
", Kth(rt[i], t[rt[i]].size - res + 1)); 
		} 
	} 
	return 0; 
} 
原文地址:https://www.cnblogs.com/heyujun/p/10101269.html