[洛谷P2286][题解][HNOI2004]宠物收养场

题目

0.写在前面

终于靠这道题完成了寒假以来十棵平衡树的flag。。。
特著此题解以纪念

1.思路

可能有人会想到维护两个平衡树,但当你读过题之后就会发现:
人和宠物本质是一样的!!!
所以,写一棵就够了。
其他的都是模板,相信做到这种题的巨佬肯定都会了,不做细讲。
领养/被领养的步骤按题意模拟即可。

2.细节

关于平衡树的选用随便啦~反正我是 Splay 党~
取领养/被领养的家伙的时候要注意取等号!!!

3.代码

缺省源?自己找!

#define N 80010
#define mod 1000000
int n,root,tot,ans;//有人说ans要LL,其实膜好了不需要LL的 
int fa[N],ch[N][2];
int data[N],siz[N];
int st;//来人+1,来宠物-1

//-----*平衡树基本操作始*-----// 
inline int Son(int k){
	return ch[fa[k]][1]==k;
}
inline void Pushup(int k){
	siz[k]=siz[ls]+siz[rs]+1;
}
inline void Rotate(int k){
	int fk=fa[k],gfk=fa[fk];
	int b=Son(k),c=Son(fk),a=ch[k][!b];
	ch[gfk][c]=k,fa[k]=gfk;
	ch[fk][b]=a,fa[a]=fk;
	ch[k][!b]=fk,fa[fk]=k;
	Pushup(k),Pushup(fk);
}
inline void Splay(int k,int to=0){
	while(fa[k]!=to){
		int fk=fa[k],gfk=fa[fk];
		if(gfk!=to){
			if(Son(k)==Son(fk))Rotate(fk);
			else Rotate(k);
		}
		Rotate(k);
	}
	if(!to)root=k;
}
inline void Insert(int num){
	int k=root,tmp=0;
	while(k&&data[k]!=num){
		tmp=k,k=ch[k][num>data[k]];
	}
	if(!k){
		k=++tot;
		if(tmp)ch[tmp][num>data[tmp]]=k;
		fa[k]=tmp,data[k]=num;
		ls=rs=0;
	}
	Splay(k);
}
inline void Find(int num){
	int k=root;
	while(data[k]!=num&&ch[k][num>data[k]]){
		k=ch[k][num>data[k]];
	}
	Splay(k);
}
inline int Get(int num,int opt){
	Find(num);
	int k=root;
	if(opt&&num<data[k])return k;
	if(!opt&&num>data[k])return k;
	k=ch[k][opt];
	while(ch[k][opt^1])k=ch[k][opt^1];
	return k;
}
inline int Gete(int num,int opt){
	Find(num);
	int k=root;
	if(opt&&num<=data[k])return k;
	if(!opt&&num>=data[k])return k;
	k=ch[k][opt];
	while(ch[k][opt^1])k=ch[k][opt^1];
	return k;
}
inline void Delete(int num){
	int l=Get(num,0),r=Get(num,1);
	Splay(l),Splay(r,l);
	ch[r][0]=0;
}
//-----*平衡树基本操作完*-----// 

int main(){
	Insert(-INF),Insert(INF);//防爆基本操作 
	Read(n);
	for(rg int i=1;i<=n;i++){
		int opt,num;
		Read(opt),Read(num);
		if(st==0)Insert(num);//空了 
		else if(st<0){//全是宠物 
			if(opt==1)Insert(num);
			else {
				int pred=data[Gete(num,0)];
				int sufd=data[Gete(num,1)];
				if(abs(pred-num)<=abs(sufd-num)){
					ans=(ans+abs(pred-num))%mod;
					Delete(pred);
				}else {
					ans=(ans+abs(sufd-num))%mod;
					Delete(sufd);
				}
			}
		}else {//全是人 
			if(opt==0)Insert(num);
			else {
				int pred=data[Gete(num,0)];
				int sufd=data[Gete(num,1)];
				if(abs(pred-num)<=abs(sufd-num)){
					ans=(ans+abs(pred-num))%mod;
					Delete(pred);
				}else {
					ans=(ans+abs(sufd-num))%mod;
					Delete(sufd);
				}
			}
		}
		st+=(opt==0)?1:-1;
	}
	cout<<ans<<endl;
	return 0;
}

4.完结撒花

posted @ 2020-05-02 18:04  ajthreac  阅读(152)  评论(1编辑  收藏  举报