一些东西

template<typename T>
class Balanced_Tree{
	private:
		struct node{
			int ls,rs,num,siz;
			T val;
			int cnt;
		};
		node *tr;
		int *id;
		int cnt,tot;
		const double B=0.80;
		T Min,Max;
		void GetID(int p){
			if(tr[p].ls) GetID(tr[p].ls);
			if(tr[p].num>tr[tr[p].ls].num+tr[tr[p].rs].num) id[++cnt]=p;
			if(tr[p].rs) GetID(tr[p].rs);
			tr[p].ls=tr[p].rs=0;
		}
		int ReBuild(int l,int r){
			if(r<l) return 0;
			int mid=l+r>>1;
			int rt=id[mid];
			tr[rt].ls=ReBuild(l,mid-1);
			tr[rt].rs=ReBuild(mid+1,r);
			tr[rt].num=tr[rt].cnt+tr[tr[rt].ls].num+tr[tr[rt].rs].num;
			tr[rt].siz=tr[tr[rt].ls].siz+tr[tr[rt].rs].siz+1;
			return rt;
		}
		void insert(int& p,T x){
			if(!p){
				p=++tot;
				tr[p]={0,0,1,1,x,1};
				return;
			}
			if(tr[p].val==x){
				tr[p].num++;
				tr[p].cnt++;
				return;
			}
			if(tr[p].val>x) insert(tr[p].ls,x);
			if(tr[p].val<x) insert(tr[p].rs,x);
			tr[p].num++;
			tr[p].siz=tr[tr[p].ls].siz+tr[tr[p].rs].siz+1;
			if(1.0*max(tr[tr[p].ls].siz,tr[tr[p].rs].siz)>1.0*B*tr[p].siz){
				cnt=0;
				GetID(p);
				p=ReBuild(1,cnt);
			}
		}
		void del(int p,T x){
			if(tr[p].val==x){
				if(tr[p].cnt) tr[p].num--,tr[p].cnt--;
				return;
			}
			if(tr[p].val>x&&tr[p].ls) del(tr[p].ls,x);
			if(tr[p].val<x&&tr[p].rs) del(tr[p].rs,x);
			tr[p].num=tr[p].cnt+tr[tr[p].ls].num+tr[tr[p].rs].num;
			tr[p].siz=tr[tr[p].ls].siz+tr[tr[p].rs].siz+1;
		}
		T gn(int p,int rk){
			if(rk-tr[tr[p].ls].num>0&&rk<=tr[p].num-tr[tr[p].rs].num) return tr[p].val;
			if(rk<=tr[tr[p].ls].num) return gn(tr[p].ls,rk);
			else return gn(tr[p].rs,rk-tr[p].num+tr[tr[p].rs].num);
		}
	public:
		int Root;
		void Build(int N){
			cnt=tot=0;
			tr=new node[N];
			id=new int[N];
		}
		bool Empty(){
			return !tr[Root].num;
		}
		void Set(T minn,T maxx){
			Min=minn,Max=maxx;
		}
		void Clear(){
			cnt=tot=0;
		}
		void Insert(T x){
			insert(Root,x);
		}
		void Delete(int x){
			del(Root,x);
		}
		int GetCount(T x){
			int p=Root;
			while(p&&tr[p].val!=x){
				if(tr[p].val>x) p=tr[p].ls;
				else p=tr[p].rs;
			}
			if(p) return tr[p].cnt;
			return 0;
		}
		int GetRank(T x){
			int ans=0,p=Root;
			while(p&&tr[p].val!=x){
				if(tr[p].val<x) ans+=tr[p].cnt+tr[tr[p].ls].num,p=tr[p].rs;
				else p=tr[p].ls;
			}
			return ans+tr[tr[p].ls].num+1;
		}
		T GetVal(int rk){
			if(rk<1) return Min;
			if(rk>tr[Root].num) return Max;
			return gn(Root,rk);
		}
		T GetPrev(T x){
			assert(!Empty());
			return GetVal(GetRank(x)-1);
		}
		T GetNext(T x){
			assert(!Empty());
			return GetVal(GetRank(x)+GetCount(x));
		}
};

定义方式:

Balanced_Tree<Type> Name;

需要定义大于号、小于号。
支持操作:

  1. Name.Build(int N) 建树(其实就是申请空间)\(O(1)\)
  2. Name.Insert(T x) 插入一个元素 \(O(\log n)\)
  3. Name.Delete(T x) 删除一个元素(如有多个只删除一个,没有就不删)\(O(\log n)\)
  4. Name.GetRank(T x) 求排名(准确来说是小于这个值的元素的个数加一) \(O(\log n)\)
  5. Name.GetVal(int rk) 根据排名求值 \(O(\log n)\)
  6. Name.GetPrev(T x) 前驱 \(O(\log n)\)
  7. Name.GetNext(T x) 后继 \(O(\log n)\)
  8. Name.GetCount(T x) 求某一个值出现的次数 \(O(\log n)\)
  9. Name.Clear() 清空 \(O(1)\)
  10. Name.Set(T minn,T maxx) 设置极大值、极小值(用于求前驱后继)\(O(1)\)

据 fqr 说,在这道题中总时间跑进 \(10\text{s}\) 就算比较快了,用这个平衡树再加上 fread 可以获得总时间 \(8\text{s}\)好成绩

posted @ 2025-04-29 20:59  Fiendish  阅读(21)  评论(0)    收藏  举报