萌新刚学 OI 第一天,0 分 Splay 求助!
查看原帖
萌新刚学 OI 第一天,0 分 Splay 求助!
363036
chlchl楼主2022/3/12 11:50

rt,TLE+WA.

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int n, rt, sum;
struct Splay{
	int fa, val, cnt, sz, son[2];//0 left, 1 right
} spy[N];

bool direction(int x, int fa){return spy[fa].son[1] == x;}

void update(int u){spy[u].sz = spy[spy[u].son[0]].sz + spy[spy[u].son[1]].sz + spy[u].cnt;}

void rebuild(int x, int fa, int d){//d 是左边 or 右边的标记 
	spy[fa].son[d] = x, spy[x].fa = fa;
}

void rotate(int x){//单旋 
	int fa = spy[x].fa, g = spy[fa].fa;
	int d = direction(x, fa);//右旋回 0 左旋回 1 
	rebuild(x, g, direction(fa, g));
	rebuild(spy[x].son[d ^ 1], fa, d);//什么旋处理什么儿子 
	rebuild(fa, x, d ^ 1);//更换 x 和 fa 的父子关系
	update(fa), update(x);
}

void newnode(int &u, int &val, int fa){
	u = sum++;
	spy[u].fa = fa, spy[u].val = val, spy[u].sz++, spy[u].cnt++;
}

void splay(int x, int y){//把 x 转到 y 的位置 
	if(!y)	rt = x;
    while(spy[x].fa != y){
        int f = spy[x].fa, g = spy[f].fa;
        if(g != y)	direction(f, g) ^ direction(x, f) ? rotate(x) : rotate(f);
		//原本要分四种情况,但因为 rotate 合二为一,所以有的情况在 rotate 里讨论了
        rotate(x);//最后一次都是旋转 x
    }
}

void insert(int &u, int fa, int val){
	if(!u)	newnode(u, val, fa), splay(u, 0);
	else if(val < spy[u].val)	insert(spy[u].son[0], u, val);
	else	insert(spy[u].son[1], u, val);
}

void delnode(int u){
	splay(u, 0);
	if(spy[u].cnt > 1)	spy[u].cnt--, spy[u].sz--;
	else if(!spy[rt].son[1])	rt = spy[u].son[0], spy[rt].fa = 0;//转完发现没有右儿子,直接把根定为左儿子
	else{
		int nxt = spy[u].son[1];
        while(spy[nxt].son[0])	nxt = spy[nxt].son[0];//找后继 
        splay(nxt, u);
        rebuild(spy[u].son[0], nxt, 0);
		rt = nxt, spy[nxt].fa = 0;
        update(rt);
	}
	return ;
}

void del(int u, int &val){
	if(spy[u].val == val)	delnode(u);
	else if(spy[u].val > val)	del(spy[u].son[0], val);
	else	del(spy[u].son[1], val);
}

int rnk(int x){
	int u = rt, rk = 1, v = 0;
	while(u){
		if(x <= spy[u].val)    v = u, u = spy[u].son[0];
		else	rk += spy[spy[u].son[0]].sz + 1, u = spy[u].son[1];
    }
    if(v)	splay(v, 0);
    return rk;
}

int query(int rk){
	int u = rt;
	while(u){
		if(spy[spy[u].son[0]].sz + 1 == rk){
			splay(u, 0);
			break;
		}
		else if(spy[spy[u].son[0]].sz >= rk)	u = spy[u].son[0];
		else	rk -= spy[spy[u].son[0]].sz + 1, u = spy[u].son[1];
	}
	return spy[u].val;
}

int main(){
    scanf("%d", &n);
	int op, x;
    while(n--){
        scanf("%d%d", &op, &x);
		if(op == 1)	insert(rt, 0, x);
		else if(op == 2)	del(rt, x);
		else if(op == 3)	printf("%d\n", rnk(x));
		else if(op == 4)	printf("%d\n", query(x));
		else if(op == 5)	printf("%d\n", query(rnk(x) - 1));
		else if(op == 6)	printf("%d\n", query(rnk(x + 1)));
    }
    return 0;
}
2022/3/12 11:50
加载中...