洛谷 P3369 【模板】普通平衡树 【无旋treap、Splay、pb_ds】

题目链接
题意:

写一种数据结构,来维护一些数,其中需要提供以下操作:

  1. 插入 xx 数
  2. 删除 xx 数(若有多个相同的数,因只删除一个)
  3. 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 )
  4. 查询排名为 xx 的数
  5. 求 xx 的前驱(前驱定义为小于 xx,且最大的数)
  6. 求 xx 的后继(后继定义为大于 xx,且最小的数)

题解:

平衡树的模板题,但是treap相较于其他的BST更好写、更好理解

#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>
#define int long long
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))
const int mod = 1e9+7;
using namespace std;
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;
}
#define endl '\n'
const int INF = 0x3f3f3f3f;
const int N = 1e6+10;
const int maxn = 1e3+10;

struct node{
	int l,r;
	int val,key;
	int sz;
}fhq[N];
int cnt,root;
mt19937 rng(time(NULL));
int newnode(int val){
	fhq[++cnt].val=val;
	fhq[cnt].key=rng();//给每个节点随机分配一个优先级
	fhq[cnt].sz=1;
	return cnt;
}
void update(int now){
	fhq[now].sz=fhq[fhq[now].l].sz+fhq[fhq[now].r].sz+1;
}
void split(int now,int val,int &x,int &y){
	if(!now) x=y=0;
	else{
		if(fhq[now].val<=val){
			x=now;
			split(fhq[now].r,val,fhq[now].r,y);
		}
		else{
			y=now;
			split(fhq[now].l,val,x,fhq[now].l);
		}
		update(now);
	}
}
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;
	}
}
int x,y,z;
void ins(int val){
    split(root,val,x,y);
    root=merge(merge(x,newnode(val)),y);
}
void del(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 val){
    split(root,val-1,x,y);
    cout<<fhq[x].sz+1<<endl;
    root=merge(x,y);
}
void getnum(int rank){
    int now=root;
    while(now){
        if(fhq[fhq[now].l].sz+1==rank)
            break;
        else if(fhq[fhq[now].l].sz>=rank)
            now=fhq[now].l;
        else {
            rank-=fhq[fhq[now].l].sz+1;
            now=fhq[now].r;
        }
    }
    cout<<fhq[now].val<<endl;
}
void pre(int val){
    split(root,val-1,x,y);
    int now = x;
    while(fhq[now].r) now=fhq[now].r;
    cout<<fhq[now].val<<endl;
    root=merge(x,y);
}
void nxt(int val){
    split(root,val,x,y);
    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 t; cin>>t;
	while(t--){
		int opt,x;cin>>opt>>x;
        if(opt==1)ins(x);
        if(opt==2)del(x);
        if(opt==3)getrank(x);
        if(opt==4)getnum(x);
        if(opt==5)pre(x);
        if(opt==6)nxt(x);
	}
}

Splay好难写啊。。。

#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))

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;
struct node{
	int ch[2];
	int fa,val,siz;
}spy[N];
int cnt,root;
void update(int x){ spy[x].siz=spy[spy[x].ch[0]].siz+spy[spy[x].ch[1]].siz+1; }
bool ident(int x,int f){ return spy[f].ch[1]==x; }
void connect(int x,int f,int s){ spy[f].ch[s]=x,spy[x].fa=f; }
void newnode(int &now,int fa,int val){ spy[now=++cnt]={{0,0},fa,val,1}; }
void rotate(int x){
	int f=spy[x].fa, ff=spy[f].fa, k=ident(x,f);
	connect(spy[x].ch[k^1],f,k), connect(x,ff,ident(f,ff)), connect(f,x,k^1);
	update(f),update(x);
}
void splay(int x,int top){
	if(!top)root=x;
	while(spy[x].fa!=top){
		int f=spy[x].fa,ff=spy[f].fa;
		if(ff!=top) ident(f,ff)^ident(x,f)?rotate(x):rotate(f);
		rotate(x);
	}
}
void ins(int val,int &now=root,int fa=0){
	if(!now) newnode(now,fa,val),splay(now,0);
	else if(val<spy[now].val) ins(val,spy[now].ch[0],now);
	else ins(val,spy[now].ch[1],now);
}
void delnode(int x){
	splay(x,0);
	if(spy[x].ch[1]){
		int p=spy[x].ch[1];
		while(spy[p].ch[0])p=spy[p].ch[0];
		splay(p,x);
		connect(spy[x].ch[0],p,0);
		root=p, spy[p].fa=0;
		update(root);
	}
	else root=spy[x].ch[0],spy[root].fa=0;
}
void del(int val,int now=root){
	if(val==spy[now].val) delnode(now);
	else if(val<spy[now].val) del(val,spy[now].ch[0]);
	else del(val,spy[now].ch[1]);
}
int getrank(int val){
	int now=root,rank=1,pre=0;
	while(now){
		//cout<<val<<" and "<<spy[now].val<<endl;
		if(val<=spy[now].val) pre=now,now=spy[now].ch[0];
		else rank+=spy[spy[now].ch[0]].siz+1,now=spy[now].ch[1];
	}
	if(pre) splay(pre,0);
	return rank;
}
int getnum(int rank){
	int now=root;
	while(now){
		if(spy[spy[now].ch[0]].siz+1==rank){
			splay(now,0); break;
		}
		else if(spy[spy[now].ch[0]].siz>=rank)now=spy[now].ch[0];
		else rank-=spy[spy[now].ch[0]].siz+1,now=spy[now].ch[1];
	}
	return spy[now].val;
}
//#define endl '\n'
signed main(){
	//freopen("C:\\Users\\egoist\\Desktop\\in.txt","r",stdin);
	//freopen("C:\\Users\\egoist\\Desktop\\out.txt","w",stdout);
	std::ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int t; cin>>t; 
	while(t--){
		int opt,x; cin>>opt>>x;
		if(opt==1) ins(x);
		if(opt==2) del(x);
		if(opt==3) cout<<getrank(x)<<endl;
		if(opt==4) cout<<getnum(x)<<endl;
		if(opt==5) cout<<getnum(getrank(x)-1)<<endl;
		if(opt==6) cout<<getnum(getrank(x+1))<<endl;
	//	
	}
}

pbds(??? 6行就完事了?)

#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<list>
#include<bitset>
#include<algorithm>
#include<cstdio>
#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/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))

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;

tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>rb;
#define endl '\n'
signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int q; cin>>q;
	for(int i=1;i<=q;i++){
		int op,k; cin>>op>>k;
		if(op==1) rb.insert((k<<20)+i);
		if(op==2) rb.erase(rb.lower_bound(k<<20));
		if(op==3) cout<<rb.order_of_key(k<<20)+1<<endl;;
		if(op==4) cout<<((*rb.find_by_order(k-1))>>20)<<endl;
		if(op==5) cout<<((*--rb.lower_bound(k<<20))>>20)<<endl;
		if(op==6) cout<<((*rb.upper_bound((k<<20)+q))>>20)<<endl;
	}
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值