[bzoj1208][HNOI2004]宠物收养所

Description

最近,阿\(Q\)开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.
每个领养者都希望领养到自己满意的宠物,阿\(Q\)根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值\(a\),而他也给每个处在收养所的宠物一个特点值.这样他就能够很方便的处理整个领养宠物的过程了.
宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少.

  1. 被遗弃的宠物过多时,假若到来一个领养者,这个领养者希望领养的宠物的特点值为\(a\),那么它将会领养一只目前未被领养的宠物中特点值最接近\(a\)的一只宠物.(任何两只宠物的特点值都不可能是相同的,任何两个领养者的希望领养宠物的特点值也不可能是一样的)如果有两只满足要求的宠物,即存在两只宠物他们的特点值分别为\(a-b,a+b\),那么领养者将会领养特点值为\(a-b\)的那只宠物.
  2. 收养宠物的人过多时,假若到来一只被收养的宠物,那么哪个领养者能够领养它呢?能够领养它的领养者,是那个希望被领养宠物的特点值最接近该宠物特点值的领养者,如果该宠物的特点值为\(a\),存在两个领养者他们希望领养宠物的特点值分别为\(a-b,a+b\),那么特点值为\(a-b\)的那个领养者将成功领养该宠物.
    一个领养者领养了一个特点值为\(a\)的宠物,而它本身希望领养的宠物的特点值为\(b\),那么这个领养者的不满意程度为\(|a-b|\).
    你得到了一年当中,领养者和被收养宠物到来收养所的情况,希望你计算所有收养了宠物的领养者的不满意程度的总和.这一年初始时,收养所里面既没有宠物,也没有领养者.

Input

第一行为一个正整数\(n\),表示一年当中来到收养所的宠物和领养者的总数.
接下来的\(n\)行,按到来时间的先后顺序描述了一年当中来到收养所的宠物和领养者的情况.每行有两个正整数\(a,,b\),其中\(a=0\)表示宠物,\(a=1\)表示领养者,\(b\)表示宠物的特点值或是领养者希望领养宠物的特点值.(同一时间呆在收养所中的,要么全是宠物,要么全是领养者,这些宠物和领养者的个数不会超过\(10^4\)个).

Output

仅有一个正整数,表示一年当中所有收养了宠物的领养者的不满意程度的总和\(mod\;10^6\)以后的结果.

Sample Input

5
0 2
0 4
1 3
1 2
1 5

Sample Output

3

HINT

\(0<a<2^{31},n\leq80000\).

Solution

\(Splay\)查询前驱后继比较后记录删除即可.

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 80005
#define M 1000000
using namespace std;
struct BBT{
	int c[2],f,siz,cnt,val;
}tr[N];
int n,rt,cnt,lst,ans;
inline int read(){
	int ret=0;char c=getchar();
	while(!isdigit(c))
		c=getchar();
	while(isdigit(c)){
		ret=(ret<<1)+(ret<<3)+c-'0';
		c=getchar();
	}
	return ret;
}
inline bool son(int u){
	return tr[tr[u].f].c[1]==u;
}
inline void recnt(int u){
	tr[u].siz=tr[u].cnt+tr[tr[u].c[0]].siz+tr[tr[u].c[1]].siz; 
}
inline int find(int x){
	int u=rt;
	while(tr[u].val!=x&&u){
		if(x<tr[u].val)
			u=tr[u].c[0];
		else u=tr[u].c[1];
	}
	return u;
}
inline void ins_p(int f,int u,int c){
	tr[u].f=f;tr[f].c[c]=u;
}
inline void rotate(int u){
	int f=tr[u].f;bool c=son(u);
	ins_p(tr[f].f,u,son(f));
	ins_p(f,tr[u].c[c^1],c);
	ins_p(u,f,c^1);
	recnt(f);recnt(u);
	if(!tr[u].f) rt=u; 
}
inline void splay(int u){
	while(tr[u].f){
		if(!tr[tr[u].f].f) rotate(u);
		else{
			if(son(u)==son(tr[u].f)){
				rotate(tr[u].f);rotate(u);
			}
			else{
				rotate(u);rotate(u);
			}
		}
	}
} 
inline void insert(int x){
	int u=find(x),f=0;
	if(u){
		++tr[u].cnt;
		while(u){
			recnt(u);u=tr[u].f;
		}
		return;
	}
	u=rt;
	while(u){
		f=u;
		if(x<tr[u].val) 
			u=tr[u].c[0];
		else u=tr[u].c[1];
	}
	tr[++cnt].val=x;
	tr[cnt].siz=tr[cnt].cnt=1;
	if(!f){
		rt=cnt;recnt(rt);return;
	}
	if(x<tr[f].val)
		ins_p(f,cnt,0);
	else ins_p(f,cnt,1);
	splay(cnt);
}
inline int near(int u,int c){
	if(tr[u].c[c]){
		u=tr[u].c[c];c^=1;
		while(tr[u].c[c])
			u=tr[u].c[c];
		return u;
	}
	if(son(u)==c^1) return tr[u].f;
	while(son(u)==c){
		if(u==rt) return 0;
		u=tr[u].f;
	}
	return tr[u].f;
}
inline int ask(int x){
	int u=find(x),f=0,v;
	if(u) return u;
	u=rt;
	while(tr[u].val!=x&&u){
		f=u;
		if(x<tr[u].val)
			u=tr[u].c[0];
		else u=tr[u].c[1];
	}
	u=f;
	if(tr[f].val<x)
		v=near(f,1);
	else v=near(f,0);
	if(!u||!v) return u?u:v;
	return abs(tr[u].val-x)<=abs(tr[v].val-x)?u:v;
}
inline void clear(int u){
	tr[tr[u].f].c[son(u)]=0;
	recnt(tr[u].f);
	tr[u].c[0]=tr[u].c[1]=tr[u].f=tr[u].siz=tr[u].cnt=tr[u].val=0;
}
inline void del(int u){
	int lst=near(u,0),nxt=near(u,1);
	if(!lst||!nxt){
		splay(u);
		if(lst){
			rt=tr[u].c[0];
			tr[tr[u].c[0]].f=0;
		}
		else{
			rt=tr[u].c[1];
			tr[tr[u].c[1]].f=0;
		}
		return;
	}
	splay(lst);splay(nxt);
	rotate(lst);clear(u); 
}
inline void print(int u){
	if(!u) return;
	printf("%d->(%d,%d),",u,tr[u].c[0],tr[u].c[1]);
	printf("cnt=%d,siz=%d,val=%d,f=%d\n"\
	  ,tr[u].cnt,tr[u].siz,tr[u].val,tr[u].f); 
	print(tr[u].c[0]);print(tr[u].c[1]);
}
inline void Aireen(){
	int u,w;n=read();
	while(n--){
		if(!tr[rt].siz){
			lst=read();
			insert(read());
		}
		else if(lst!=read()){
			w=read();u=ask(w);
			ans=(ans+1ll*abs(w-tr[u].val))%M;
			del(u);
		}
		else insert(read());
	}
	printf("%d\n",ans);
}
int main(){
	freopen("pet.in","r",stdin);
	freopen("pet.out","w",stdout);
	Aireen();
	fclose(stdin);
	fclose(stdout);
	return 0;
}

2017-03-28 23:38:34

posted @ 2021-11-26 20:11  Aireen_Ye  阅读(41)  评论(0编辑  收藏  举报
底部 顶部 留言板 归档 标签
Der Erfolg kommt nicht zu dir, du musst auf den Erfolg zugehen.