题解 P2286 【[HNOI2004]宠物收养场】

这是题目链接

大家好,这个题我调了很久过了,所以想写题解
我用的平衡树是AVL树,平衡树界的老爷爷
这个树并不会很慢,主要是我初学,常数巨大
而且题目的 $ n = 80000$,可以接受

\(solution\):

开两颗平衡树,维护宠物和人,过多就插入自己的平衡树,过少就在对立平衡树中删除与 \(x\) 相差最小的。

也就是确定前驱后继

代码很长,但是操作是相同的,一半都是在复制粘贴

希望注意传参引用,少写一个调了很长时间

\(code:\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 80000+50;
const int mod = 1000000;
int ans;
inline void read(int &k) {
	k=0;char ch=getchar();
	while(ch>'9'||ch<'0') ch=getchar();
	while(ch<='9'&&ch>='0') k=k*10+ch-'0',ch=getchar();
}
namespace pet{
	int root,cnt;
	struct node{
		int l,r,val,height,size;
	}avl[N];
	inline void newnode(int &now,int val) {
		avl[now=++cnt].val=val,avl[now].size=1;
	}
	int factor(int now) {
		return avl[avl[now].l].height-avl[avl[now].r].height;
	}
	void update(int now) {
		avl[now].size=avl[avl[now].l].size+avl[avl[now].r].size+1;
		avl[now].height=max(avl[avl[now].l].height,avl[avl[now].r].height)+1;
	}
	void zag(int &now) {
		int r=avl[now].r;
		avl[now].r=avl[r].l;
		avl[r].l=now;
		now=r;
		update(avl[now].l),update(now);
	}
	void zig(int &now) {
		int l=avl[now].l;
		avl[now].l=avl[l].r;
		avl[l].r=now;
		now=l;
		update(avl[now].r),update(now);
	}
	void check(int &now) {
		int bf=factor(now);
		if(bf>1) {
			int lf=factor(now);
			if(lf>0) zig(now);
			else zag(avl[now].l),zig(now);
		}else if(bf<-1) {
			int rf=factor(now);
			if(rf<0) zag(now);
			else zig(avl[now].r),zag(now);
		}else if(now) update(now);
	}
	void ins(int &now,int val) {
		if(!now) newnode(now,val);
		else if(avl[now].val>val) ins(avl[now].l,val);
		else ins(avl[now].r,val);
		check(now);
	}
	int find(int &now,int fa) {
		int tmp;
		if(!avl[now].l) tmp=now,avl[fa].l=avl[now].r;
		else tmp=find(avl[now].l,now),check(now);
		return tmp;
	}
	void del(int &now,int val) {
		if(avl[now].val==val) {
			int l=avl[now].l,r=avl[now].r;
			if(!l||!r) now=l+r;
			else {
				now=find(r,r);
				if(now!=r) avl[now].r=r;
				avl[now].l=l;
			}
		}else if(avl[now].val>val) del(avl[now].l,val);
		else del(avl[now].r,val);
		check(now);
	}
	int getrank(int val) {
		int now=root,rank=1;
		while(now) {
			if(val<=avl[now].val) now=avl[now].l;
			else rank+=avl[avl[now].l].size+1,now=avl[now].r;
		}
		return rank;
	}
	int getnum(int rank) {
		int now=root;
		while(now) {
			if(rank==avl[avl[now].l].size+1) break;
			else if(rank<=avl[avl[now].l].size) now=avl[now].l;
			else rank-=avl[avl[now].l].size+1,now=avl[now].r;
		}
		return avl[now].val;
	}
	int search(int now,int val) {
		if(!now) return false;
		if(val==avl[now].val) return true;
		else if(val<avl[now].val) return search(avl[now].l,val);
		else return search(avl[now].r,val);
		return false;
	}
}
namespace human{
	int root,cnt;
	struct node{
		int l,r,val,height,size;
	}avl[N];
	inline void newnode(int &now,int val) {
		avl[now=++cnt].val=val,avl[now].size=1;
	}
	int factor(int now) {
		return avl[avl[now].l].height-avl[avl[now].r].height;
	}
	void update(int now) {
		avl[now].size=avl[avl[now].l].size+avl[avl[now].r].size+1;
		avl[now].height=max(avl[avl[now].l].height,avl[avl[now].r].height)+1;
	}
	void zag(int &now) {
		int r=avl[now].r;
		avl[now].r=avl[r].l;
		avl[r].l=now;
		now=r;
		update(avl[now].l),update(now);
	}
	void zig(int &now) {
		int l=avl[now].l;
		avl[now].l=avl[l].r;
		avl[l].r=now;
		now=l;
		update(avl[now].r),update(now);
	}
	void check(int &now) {
		int bf=factor(now);
		if(bf>1) {
			int lf=factor(now);
			if(lf>0) zig(now);
			else zag(avl[now].l),zig(now);
		}else if(bf<-1) {
			int rf=factor(now);
			if(rf<0) zag(now);
			else zig(avl[now].r),zag(now);
		}else if(now) update(now);
	}
	void ins(int &now,int val) {
		if(!now) newnode(now,val);
		else if(avl[now].val>val) ins(avl[now].l,val);
		else ins(avl[now].r,val);
		check(now);
	}
	int find(int &now,int fa) {
		int tmp;
		if(!avl[now].l) tmp=now,avl[fa].l=avl[now].r;
		else tmp=find(avl[now].l,now),check(now);
		return tmp;
	}
	void del(int &now,int val) {
		if(avl[now].val==val) {
			int l=avl[now].l,r=avl[now].r;
			if(!l||!r) now=l+r;
			else {
				now=find(r,r);
				if(now!=r) avl[now].r=r;
				avl[now].l=l;
			}
		}else if(avl[now].val>val) del(avl[now].l,val);
		else del(avl[now].r,val);
		check(now);
	}
	int getrank(int val) {
		int now=root,rank=1;
		while(now) {
			if(val<=avl[now].val) now=avl[now].l;
			else rank+=avl[avl[now].l].size+1,now=avl[now].r;
		}
		return rank;
	}
	int getnum(int rank) {
		int now=root;
		while(now) {
			if(rank==avl[avl[now].l].size+1) break;
			else if(rank<=avl[avl[now].l].size) now=avl[now].l;
			else rank-=avl[avl[now].l].size+1,now=avl[now].r;
		}
		return avl[now].val;
	}
	int search(int now,int val) {
		if(!now) return false;
		if(val==avl[now].val) return true;
		else if(val<avl[now].val) return search(avl[now].l,val);
		else return search(avl[now].r,val);
		return false;
	}
}
signed main() {
	int n; cin>> n;
	while(n--) {
		int opt, x;
//		scanf("%lld%lld",&opt, &x);
		read(opt),read(x);
		if(!opt) {
			if(human::avl[human::root].size) {
				if(human::search(human::root,x)) human::del(human::root,x);
				else {
					int pre=human::getnum(human::getrank(x)-1);
					int nxt=human::getnum(human::getrank(x+1));
					if(pre==0) { ans+=nxt-x,ans%=mod,human::del(human::root,nxt);continue;}
					if(nxt==0) { ans+=x-pre,ans%=mod,human::del(human::root,pre);continue;}					
					if(x-pre<=nxt-x) ans+=x-pre,ans%=mod,human::del(human::root,pre);
					else ans+=nxt-x,ans%=mod,human::del(human::root,nxt);
				}
			}else pet::ins(pet::root,x);
		}else {
			if(pet::avl[pet::root].size) {
				if(pet::search(pet::root,x)) pet::del(pet::root,x);
				else {
					int pre=pet::getnum(pet::getrank(x)-1);
					int nxt=pet::getnum(pet::getrank(x+1));
					if(pre==0) { ans+=nxt-x,ans%=mod,pet::del(pet::root,nxt);continue;}
					if(nxt==0) { ans+=x-pre,ans%=mod,pet::del(pet::root,pre);continue;}
					if(x-pre<=nxt-x) ans+=x-pre,ans%=mod,pet::del(pet::root,pre);
					else ans+=nxt-x,ans%=mod,pet::del(pet::root,nxt);
				}
			}else human::ins(human::root,x);			
		}
	}
	cout<<ans;	
	return 0;
}
posted @ 2019-12-22 15:24  skkyk  阅读(206)  评论(1编辑  收藏  举报