• [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

  • 相关阅读:
    获取父子栏目内容的知识点总结:更多信息页面的信息内容获取
    获取栏目内容的知识点总结:SingleInfoSortPortlet类型笔记(单栏目的获取)
    JBPM插件安装(MyEclipse8.5测试成功)和配置
    获取栏目内容的知识点总结:KnobInfoSortPortlet类型笔记(没有层级关系的栏目信息)
    HTML的事件说明
    正交投影、格拉姆施密特正交(一)
    子级Repeater获取父级Repeater绑定项的值
    启用IIS6的Gzip压缩功能
    属性IsLocked不可用于登录"[sa]解决办法
    在IE流览器中正确显示PNG透明图片
  • 原文地址:https://www.cnblogs.com/AireenYe/p/bzoj1208.html
Copyright © 2020-2023  润新知