Splay 过样例 WA 0 分求助
查看原帖
Splay 过样例 WA 0 分求助
765281
ccchl42楼主2022/8/7 22:21

为了 LCT,放弃 fhq_treap 练 Splay,一来就 WA……

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

const int N = 3e5 + 10;
int n, ans, rt, tot;
ll lim;
struct splay{
	int sz, fa, cnt, son[2];
	ll val;
} t[N];

#define ls(u) (t[u].son[0])
#define rs(u) (t[u].son[1])

void newnode(int &u, ll v, int f){
	u = ++tot, t[tot].fa = f;
	t[tot].sz = t[tot].cnt = 1, t[tot].val = v;
}

void update(int u){t[u].sz = t[ls(u)].sz + t[rs(u)].sz + t[u].cnt;}

bool getson(int u, int f){return rs(f) == u;}

void rebuild(int u, int f, int d){t[f].son[d] = u, t[u].fa = f;}

void rotate(int u){
	int f = t[u].fa, g = t[f].fa;
	int d = getson(u, f), df = getson(f, g);
	rebuild(t[u].son[d ^ 1], f, d);
	rebuild(u, g, df);
	rebuild(f, u, d ^ 1);
	update(f), update(u);
}

void splay(int u, int v){
	if(!v)	rt = u;
	while(t[u].fa != v){
		int f = t[u].fa, g = t[f].fa;
		if(g != v)	getson(u, f) ^ getson(f, g) ? rotate(u) : rotate(f);//一字型转f,大于小于号转u
		rotate(u);
	}
}

ll kth(int u, int k){
	if(k >= t[u].sz)	return -1;
	++k;//第一大是那个无穷大,tmd看了半天 
	while(u){
		if(t[rs(u)].sz + t[rs(u)].cnt == k){splay(u, 0); break;}
		else if(t[rs(u)].sz + t[rs(u)].cnt > k)	u = rs(u);
		else	k -= t[rs(u)].sz + t[rs(u)].cnt, u = ls(u);
	}
	return t[u].val;
}

void insert(int &u, int fa, ll v){
    if(!u)  newnode(u, v, fa), splay(u, 0);
    else if(v == t[u].val)	++t[u].cnt;
    else if(v < t[u].val)	insert(t[u].son[0], u, v);
    else if(v > t[u].val)	insert(t[u].son[1], u, v);
}

void getpre(int v){
	int u = rt;
	while(v != t[u].val && t[u].son[v > t[u].val])	u = t[u].son[v > t[u].val];
	splay(u, 0);
}

int getnxt(int v){
    getpre(v);//需要先找前驱并旋转到根,右子树最底的左儿子就是后继
	if(t[rt].val >= v) return rt;
    int u = rs(rt);
    while(ls(u)) u = ls(u);
    return u;
}

void deltree(int v){
	int u = getnxt(v + lim);//扣工资后达到不会离开的最小工资 
	splay(u, 0);
	ans += t[ls(u)].sz;//直接删除左子树,工资比他小就全部离开了 
	t[u].son[0] = 0;//左子树设为空,断开即可 
	update(u);//由于删掉了,需要做sz的更新 
	for(int i=1;i<=tot;i++)	t[i].val -= v;
}

int main(){
	insert(rt, 0, 1e18);
	scanf("%d%lld", &n, &lim);
	while(n--){
		char s[4];
		int k;
		scanf("%s%d", s, &k);
		if(s[0] == 'I'){
			if(k < lim)	continue;
			insert(rt, 0, k);
		}else if(s[0] == 'A')	for(int i=1;i<=tot;i++)	t[i].val += k;
		else if(s[0] == 'S')	deltree(k);
		else if(s[0] == 'F')	printf("%lld\n", kth(rt, k));
	}
	printf("%d\n", ans);
	return 0;
}
2022/8/7 22:21
加载中...