可持久化 FHQ Treap

例题链接

建议优先阅读可持久化线段树

可持久化 FHQ Treap

同可持久化线段树,可持久化平衡树的原理也是充分利用过去版本信息。

split 操作中,不断复制节点即可构造新版本。

是的,结束了。

事实上,诸多可持久化数据结构都是如此原理。

例题 AC 代码

//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
#include<random>
using namespace std;
mt19937 Rand(time(0));
constexpr const int N=5e5;
struct FHQTreap{
	int root[N+1];
	int size;
	struct node{
		int value,size,rand;
		int lChild,rChild;
	}t[N*100+1];
	
	FHQTreap(){
		size=0;
	}
	int clone(int p){
		t[++size]=t[p];
		return size;
	}
	int create(int x){
		t[++size]={x,1,Rand(),0,0};
		return size;
	}
	void up(int p){
		t[p].size=t[t[p].lChild].size + 1 + t[t[p].rChild].size;
	}
	void split(int p,int x,int &l,int &r){
		if(!p){
			l=r=0;
			return;
		}
		p=clone(p);
		if(t[p].value<=x){
			l=p;
			split(t[p].rChild,x,t[p].rChild,r);
		}else{
			r=p;
			split(t[p].lChild,x,l,t[r].lChild);
		}
		up(p);
	}
	int merge(int l,int r){
		if(!l||!r){
			return l|r;
		}
		if(t[l].rand<t[r].rand){
			t[l].rChild=merge(t[l].rChild,r);
			up(l);
			return l;
		}else{
			t[r].lChild=merge(l,t[r].lChild);
			up(r);
			return r;
		}
	}
	void insert(int v,int i,int x){
		int l,r,p;
		split(root[v],x,l,r);
		root[i]=merge(merge(l,create(x)),r);
	}
	void erase(int v,int i,int x){
		int l,r,p;
		split(root[v],x,l,r);
		split(l,x-1,l,p);
		p=merge(t[p].lChild,t[p].rChild);
		root[i]=merge(merge(l,p),r);
	}
	int rank(int v,int i,int x){
		int l,r;
		split(root[v],x-1,l,r);
		int ans=t[l].size+1;
		root[i]=merge(l,r);
		return ans;
	}
	int kth(int v,int i,int k,int p=-1){
		if(p==-1){
			p=root[v];
		}
		while(true){
			if(t[t[p].lChild].size+1==k){
				break;
			}else if(t[t[p].lChild].size+1<k){
				k-=t[t[p].lChild].size+1;
				p=t[p].rChild;
			}else{
				p=t[p].lChild;
			}
		}
		root[i]=root[v];
		return t[p].value;
	}
	int prev(int v,int i,int x){
		int l,r;
		split(root[v],x-1,l,r);
		int ans=kth(0,0,t[l].size,l);
		root[i]=merge(l,r);
		return ans;
	}
	int next(int v,int i,int x){
		int l,r;
		split(root[v],x,l,r);
		int ans=kth(0,0,1,r);
		root[i]=merge(l,r);
		return ans;
	}
	
	void print(int v,int p=-1){
		if(p==-1){
			p=root[v];
		}
		if(!p){
			return;
		}
		print(v,t[p].lChild);
		cerr<<t[p].value<<' ';
		print(v,t[p].rChild);
	}
}t;
int main(){
	/*freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);*/
	
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		int v,opt,x;
		cin>>v>>opt>>x;
		switch(opt){
			case 1:
				t.insert(v,i,x);
				break;
			case 2:
				t.erase(v,i,x);
				break;
			case 3:
				cout<<t.rank(v,i,x)<<'\n';
				break;
			case 4:
				cout<<t.kth(v,i,x)<<'\n';
				break;
			case 5:
				cout<<t.prev(v,i,x)<<'\n';
				break;
			case 6:
				cout<<t.next(v,i,x)<<'\n';
				break;
		}
	}
	
	cout.flush();
	
	/*fclose(stdin);
	fclose(stdout);*/
	return 0;
}
/*
9
0 1 9
1 1 3
1 1 10
2 4 2
3 3 9
2 4 2
3 3 9
2 4 2
3 3 9
*/
posted @ 2025-08-13 16:18  TH911  阅读(9)  评论(0)    收藏  举报