替罪羊树求调捏
查看原帖
替罪羊树求调捏
664105
BalanceSegment楼主2023/4/8 19:23

因为实力太拉所以照着 OI wiki 写的,但是 WA 28pts。

个人感觉码风较好。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
const double alpha = 0.75;
struct ScapeGoatTree {
	int cnt, rt;
	int w[N], lc[N], rc[N];
	int wn[N], s[N];
	int sz[N], sd[N];
	int ldr[N];
	void Calc(int 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); 
	}
	// Rebuild 
	bool CanRbu(int k) {return wn[k]&&(alpha*s[k]<=(double)max(s[lc[k]], s[rc[k]])||(double)sd[k]<=alpha*s[k]);}
	void Rbu_Flt(int &ldc, int k) {
		if(!k) return ;
		Rbu_Flt(ldc, lc[k]);
		if(wn[k]) ldr[ldc++] = k;
		Rbu_Flt(ldc, rc[k]);
	}
	int Rbu_Bld(int l, int r) {
		int mid = l+r>>1;
		if(l>=r) return 0;
		lc[ldr[mid]] = Rbu_Bld(l, mid);
		rc[ldr[mid]] = Rbu_Bld(mid+1, r);
		Calc(ldr[mid]);
		return ldr[mid]; 
	}
	void Rbu(int &k) {
		int ldc = 0;
		Rbu_Flt(ldc, k);
		k = Rbu_Bld(0, ldc);
	}
	// Rebuild 
	void ins(int& k, int p) {
		if(!k) {
			k = ++cnt;
	    	if(!rt) rt = 1;
	    	w[k] = p;
	   	 	lc[k] = rc[k] = 0;
	  	  	wn[k] = s[k] = sz[k] = sd[k] = 1;
	  	}else {
	  	  	if(w[k]==p) wn[k]++;
	   	 	else if(w[k]<p) ins(rc[k], p);
	   	 	else ins(lc[k], p);
	   	 	Calc(k);
	   	 	if(CanRbu(k)) Rbu(k);
	  	}
	}
	void del(int& k, int p) {
	  	if(!k) return ;
	  	else {
	    	if(w[k]==p)
				if(wn[k]) wn[k]--;
	    	else {
	      		if(w[k]<p) del(rc[k], p);
	      		else del(lc[k], p);
	    	}
	    	Calc(k);
	    	if(CanRbu(k)) Rbu(k);
	  	}
	}
	int UpperBound(int k, int p) {
	  	if(!k) return 1;
	  	else if(w[k]==p&&wn[k]) return sz[lc[k]]+wn[k]+1;
	  	else if(p<w[k]) return UpperBound(lc[k], p);
	  	else return sz[lc[k]]+wn[k]+UpperBound(rc[k], p);
	}
	int LowerBound(int k, int p) {
	  	if(!k) return 0;
	  	else if(w[k]==p&&wn[k]) return sz[lc[k]];
	  	else if(w[k]<p) return sz[lc[k]]+wn[k]+LowerBound(rc[k], p);
	  	else return LowerBound(lc[k], p);
	}
	int At(int k, int p) {
		if(!k) return 0;
		else if(sz[lc[k]]<p&&p<=sz[lc[k]]+wn[k]) return w[k];
		else if(sz[lc[k]]+wn[k]<p) return At(rc[k], p-sz[lc[k]]-wn[k]);
		else return At(lc[k], p);
	}
	inline int Pre(int k, int p) {return At(k, LowerBound(k, p));}
	inline int Nxt(int k, int p) {return At(k, UpperBound(k, p));}
//	inline int Rnk(int x) {return ;}
}sgt;
int main() {
	int n, opt, x;
	cin >> n;
	while(n--) {
		cin >> opt >> x;
		if(opt==1) sgt.ins(sgt.rt, x);
		else if(opt==2) sgt.del(sgt.rt, x);
		else if(opt==3) cout << sgt.LowerBound(sgt.rt, x)+1 << endl;
		else if(opt==4) cout << sgt.At(sgt.rt, x) << endl;
		else if(opt==5) cout << sgt.Pre(sgt.rt, x) << endl;
		else if(opt==6) cout << sgt.Nxt(sgt.rt, x) << endl;
	}
	return 0;
}
2023/4/8 19:23
加载中...