FHQ-Treap 30pts(WA + TLE)
查看原帖
FHQ-Treap 30pts(WA + TLE)
999274
CNS_5t0_0r2楼主2024/7/25 16:14
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 9;
struct node{
	int val,pri;
	int lc,rc;
	int siz;
} t[N];
int node_cnt,root;

void push_up(int u){
	t[u].siz = t[t[u].lc].siz + t[t[u].rc].siz + 1;
}

void split(int u,int x,int &L,int &R){//将以u为根的子树分裂成以L,R为根的两棵子树满足左子树所有节点权值 <= x,右子树所有节点权值 > x
	if(u == 0){
		L = R = 0;
		return;
	}
	if(t[u].val <= x){
		L = u;
		split(t[u].rc,x,t[u].rc,R);
	}
	else{
		R = u;
		split(t[u].lc,x,L,t[u].lc);
	}
	push_up(u);
}
//合并的前提条件:保证 t[u].val <= t[v].val 
int merge(int u,int v){//将以u为根的树和以v为根的子树合并并返回合并后的根 
	if(!u || !v)//如果其中一个根为空那么合并后的根就是另一个根 
		return u | v;
	if(t[u].pri > t[v].pri){//u优先级大于v优先级,则u应为v的父亲(大根堆性质) 
		t[u].rc = merge(t[u].rc,v);//t[t[u].lc].val <= t[u].val <= t[v].val,所以合并t[u].rc和v
		push_up(u);
		return u;
	}
	else{//否则v应为u的父亲 
		t[v].lc = merge(u,t[v].lc);//t[t[v].rc].val >= t[v].val >= t[u].val,所以合并u和t[v].lc 
		push_up(v);
		return v;
	}
}

void new_node(int x){
	t[++node_cnt] = (node){x,rand() * rand(),0,0,1};
}
void insert(int x){
	int u,v;
	split(root,x,u,v);
	new_node(x);
	root = merge(merge(u,node_cnt),v);
}
void remove(int x){
	int u,v,w;
	split(root,x,u,v);//分裂成 <= x 的子树和 > x 的子树 
	split(u,x - 1,u,w);//分裂成 < x 的子树和 == x 的子树 
	w = merge(t[w].lc,t[w].rc);//合并 w(== x 的子树) 的左右子树 ,相当于删除了一个 x
	root = merge(merge(u,w),w);
}
int rnk(int x){
	int u,v;
	split(root,x - 1,u,v);
	int ret = t[u].siz + 1;
	merge(u,v);
	return ret;
}
int kth(int u,int x){
	int tmp = t[t[u].lc].siz + 1;
	if(x == tmp)
		return t[u].val;
	if(x < tmp)
		return kth(t[u].lc,x);
	else
		return kth(t[u].rc,x - tmp);
}
int pre(int x){
	int u,v;
	split(root,x - 1,u,v);
	int ret = kth(u,t[u].siz);
	merge(u,v);
	return ret;
}
int nex(int x){
	int u,v;
	split(root,x,u,v);
	int ret = kth(v,1);
	merge(u,v);
	return ret;
}

int main(){
	srand(time(0));
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int q;
	cin >> q;
	while(q--){
		int op,x;
		cin >> op >> x;
		if(op == 1)
			insert(x);
		if(op == 2)
			remove(x);
		if(op == 3)
			cout << rnk(x) << '\n';
		if(op == 4)
			cout << kth(root,x) << '\n';
		if(op == 5)
			cout << pre(x) << '\n';
		if(op == 6)
			cout << nex(x) << '\n';
	}
	return 0;
}
2024/7/25 16:14
加载中...