萌新12pts求调替罪羊树
查看原帖
萌新12pts求调替罪羊树
358748
Error_Yuan楼主2021/9/23 22:07

RT,为啥只AC了最后一个点?

#include <bits/stdc++.h>
#define MAXN 1000010
#define alpha 0.7
using namespace std; 
int cnt = 0,
	rt = 0,
	lc[MAXN],
	rc[MAXN],
	wn[MAXN],
	w[MAXN],
	s[MAXN],
	sz[MAXN],
	sd[MAXN],
	ldr[MAXN];
void calc(int k){
	//重新计算以k为根的子树大小
	s[k] = s[lc[k]] + s[rc[k]] + 1;
	sz[k] = sz[lc[k]] + sz[rc[k]] + wn[k];
	sd[k] = sd[lc[k]] + sd[rc[k]] + (wn[k] != 0);
}
bool canRbd(int k){
	//计算节点k是否需要重构
	return wn[k] && (alpha * s[k] <= (double)max(s[lc[k]], s[rc[k]]) ||
					(double)sd[k] <= alpha * s[k]); 
}
void flatten(int& ldc, int k){
	//中序遍历以k为根的子树
	if(!k) return;
	flatten(ldc, lc[k]);
	if(wn[k]) ldr[ldc++] = k;
	flatten(ldc, rc[k]);
}
int __rebuild(int l, int r){
	//将[l,r)重构成树,返回根节点
	int mid = (l + r) >> 1;
	if(l >= r) return 0;
	lc[ldr[mid]] = __rebuild(l, mid);
	rc[ldr[mid]] = __rebuild(mid + 1, r);
	calc(ldr[mid]);
	return ldr[mid];
}
void rebuild(int& k){
	//重构节点k的全过程
	int ldc = 0;
	flatten(ldc, k);
	k = __rebuild(0, ldc);
}
void ins(int& k, int val){
	//在以k为根的子树内插入val 
	if(!k){
		k = ++cnt;
		if(!rt) rt = 1;
		lc[k] = rc[k] = 0;
		wn[k] = s[k] = sz[k] = sd[k] = 1;
		w[k] = val;
	}else{
		if(wn[k] == val)	
			wn[k]++;
		else if(wn[k] < val)
			ins(rc[k], val);
		else
			ins(lc[k], val);
		calc(k);
		if(canRbd(k)) rebuild(k);
	}
}
void del(int& k, int val){
	if(!k) return;
	else{
		if(w[k] == val){
			if(wn[k]) wn[k]--;
		}else if(w[k] < val)
			del(rc[k], val);
		else
			del(lc[k], val);
		calc(k);
		if(canRbd(k)) rebuild(k);
	}
}
int myUpper(int k, int val){
	if(!k) return 1;
	else if(w[k] == val && wn[k] != 0)
		return sz[lc[k]] + wn[k] + 1;
	else if(val < w[k])
		return myUpper(lc[k], val);
	else return sz[lc[k]] + wn[k] + myUpper(rc[k], val);
}
int myLower(int k, int val){
	if(!k) return 0;
	else if(w[k] == val && wn[k] != 0)
		return sz[lc[k]];
	else if(w[k] < val)
		return sz[lc[k]] + wn[k] + myLower(rc[k], val);
	else return myLower(lc[k], val);
}
int myAt(int k, int rk){
	if(!k) return 0;
	else if(sz[lc[k]] < rk && rk - sz[lc[k]] <= wn[k])
		return w[k];
	else if(sz[lc[k]] + wn[k] < rk)
		return myAt(rc[k], rk - wn[k] - sz[lc[k]]);
	else return myAt(lc[k], rk);
}
int myRank(int k, int val){
	return myLower(k, val) + 1;
}
int pre(int k, int val){
	return myAt(k, myLower(k, val));
}
int post(int k, int val){
	return myAt(k, myUpper(k, val));
}
int main(){
	int n;
	cin >> n;
	while(n--){
		int opt, x;
		cin >> opt >> x;
		switch(opt){
			case 1: ins(rt, x); break;
			case 2: del(rt, x); break;
			case 3: cout << myRank(rt, x) << '\n'; break;
			case 4: cout << myAt(rt, x) << '\n'; break;
			case 5: cout << pre(rt, x) << '\n'; break;
			case 6: cout << post(rt, x) << '\n'; break;
		}
	}
	return 0;
}
2021/9/23 22:07
加载中...