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

题目链接

题意:

就是比普通平衡树多了一个持久化的操作

题解:

写起来和普通的平衡树没什么区别,因为fhq treap的根节点会变,所以要维护一下每个版本的根,然后在split的时候开个新点就好了(好像很多洛谷的题解在merge操作也开了新点,但是合并不会改变树的结点,所以开不开无所谓)

#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<algorithm>
#include<cstdio>
#include<list>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<time.h>
#include<random>
using namespace std;
#include<ext/pb_ds/priority_queue.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#include<ext/rope>
using namespace __gnu_cxx;

#define int long long
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))
#define endl '\n'
const int mod = 1e9+7;
int qpow(int a,int b){
	int ans=1;
	while(b){
		if(b&1)ans=(ans*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	return ans;
}
const int INF = 0x3f3f3f3f;
const int N = 1e6+10;
mt19937 rng(233); 
struct node{
	int l,r;
	int key,siz,val;
}fhq[N*32];
int cnt,root[N],x,y,z;
void update(int now){fhq[now].siz=fhq[fhq[now].l].siz+fhq[fhq[now].r].siz+1;}
int newnode(int val){
	fhq[++cnt]={0,0,rng(),1,val};
	return cnt;
}
void split(int now,int val,int &x,int &y){
	if(!now)x=y=0;
	else{
		if(fhq[now].val<=val){
			fhq[x=++cnt]=fhq[now];
			split(fhq[x].r,val,fhq[x].r,y);
			update(x);
		}
		else{
			fhq[y=++cnt]=fhq[now];
			split(fhq[now].l,val,x,fhq[y].l);
			update(y);
		}
	}
}
int merge(int x,int y){
	if(!x||!y)return x|y;
	if(fhq[x].key>fhq[y].key){
		fhq[x].r=merge(fhq[x].r,y);
		update(x);
		return x;
	}
	else{
		fhq[y].l=merge(x,fhq[y].l);
		update(y);
		return y;
	}
}
void ins(int &root,int val){
	split(root,val,x,y);
	root=merge(merge(x,newnode(val)),y);
}
void del(int &root,int val){
	split(root,val,x,z); split(x,val-1,x,y);
	y=merge(fhq[y].l,fhq[y].r);
	root=merge(merge(x,y),z);
}
void getrank(int &root,int val){
	split(root,val-1,x,y);
	cout<<fhq[x].siz+1<<endl;
	root=merge(x,y);
}
void getnum(int root,int rank){
	int now=root;
	while(now){
		if(fhq[fhq[now].l].siz+1==rank)break;
		else if(fhq[fhq[now].l].siz>=rank)now=fhq[now].l;
		else rank-=fhq[fhq[now].l].siz+1,now=fhq[now].r;
	}
	cout<<fhq[now].val<<endl; 
}
void getpre(int &root,int val){
	split(root,val-1,x,y);
	if(!x){
		cout<<-2147483647<<endl; return;
	}
	int now=x;
	while(fhq[now].r)now=fhq[now].r;
	cout<<fhq[now].val<<endl;
	root=merge(x,y);
}
void getnext(int &root,int val){
	split(root,val-1,x,y);
	if(!y){
		cout<<2147483647<<endl; return;
	}
	int now=y;
	while(fhq[now].l)now=fhq[now].l;
	cout<<fhq[now].val<<endl;
	root=merge(x,y);
}

signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int n; cin>>n;
	for(int i=1;i<=n;i++){
		int ver,opt,x; cin>>ver>>opt>>x;
		root[i]=root[ver];
		if(opt==1)ins(root[i],x);
		if(opt==2)del(root[i],x);
		if(opt==3)getrank(root[i],x);
		if(opt==4)getnum(root[i],x);
		if(opt==5)getpre(root[i],x);
		if(opt==6)getnext(root[i],x);
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值