zoukankan      html  css  js  c++  java
  • P2286 [HNOI2004]宠物收养场

    我是题面

    题意简单明了,两种数,如果加入一个数的时候有另一种数还存在,那就取出另一种数中与这个数差值的绝对值最小的将其删除(多个则取较小),并对答案产生它们差值的绝对值的贡献,如果没有另一种数存在,那就先将这个数存下

    平衡树裸题,直接两个平衡树维护就ok了,一个也能维护,稍麻烦一点

    线段树好像也可做,我没写,应该不难

    我写的是Splay,把Splay用结构体封装好,开两个Splay异常好写

    下面放代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cctype>
    #define ll long long
    #define gc getchar
    #define maxn 80005
    #define mo 1000000
    using namespace std;
    
    inline ll read(){
    	ll a=0;int f=0;char p=gc();
    	while(!isdigit(p)){f|=p=='-';p=gc();}
    	while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
    	return f?-a:a;
    }int n;ll ans;
    
    struct ahaha{  //Splay的结构体
    	struct ahaha1{
    		int sz,cnt,ch[2];ll v;
    	}t[maxn];int rt,tot,f[maxn];
    	#define lc t[i].ch[0]
    	#define rc t[i].ch[1]
    	inline int get(int i){return i==t[f[i]].ch[1];}
    	inline void update(int i){
    		t[i].sz=t[i].cnt+t[lc].sz+t[rc].sz;
    	}
    	inline void del(int i){
    		t[i].v=t[i].sz=t[i].cnt=f[i]=0;
    	}
    	inline int newnode(ll v){
    		int i=++tot;
    		t[i].sz=t[i].cnt=1;t[i].v=v;
    		return i;
    	}
    	inline void rotate(int x){
    		int y=f[x],z=f[y],k=get(x);
    		f[x]=z;f[t[x].ch[k^1]]=y;f[y]=x;
    		if(z)t[z].ch[y==t[z].ch[1]]=x;
    		t[y].ch[k]=t[x].ch[k^1];t[x].ch[k^1]=y;
    		update(y);update(x);
    	}
    	void Splay(int x){
    		for(int y=f[x];f[x];rotate(x),y=f[x]){
    			if(f[y])rotate(get(x)==get(y)?y:x);
    			rt=x;
    		}
    	}
    	void insert(ll v){
    		int i=rt,k;
    		if(!rt){rt=newnode(v);return;}
    		while(1){
    			k=v>t[i].v;
    			if(v==t[i].v){
    				++t[i].sz;++t[i].cnt;
    				Splay(i);return;
    			}
    			if(!t[i].ch[k]){
    				t[i].ch[k]=newnode(v);f[t[i].ch[k]]=i;
    				Splay(t[i].ch[k]);return;
    			}
    			i=t[i].ch[k];
    		}
    	}
    	void find(ll v){
    		int i=rt;
    		while(1){
    			if(v<t[i].v){
    				i=lc;
    				if(!i)return;
    			}
    			else{
    				if(!rc||v==t[i].v){
    					Splay(i);return ;
    				}
    				i=rc;
    			}
    		}
    	}
    	inline void earase(ll v){
    		find(v);int old=rt,i=rt;
    		if(t[rt].cnt!=1){--t[rt].cnt;return;}
    		if(t[rt].sz==1){del(rt);rt=0;return;}
    		if(!lc){rt=rc;f[rt]=0;del(old);return;}
    		if(!rc){rt=lc;f[rt]=0;del(old);return;}
    		i=lc;while(rc)i=rc;Splay(i);
    		t[rt].ch[1]=t[old].ch[1];f[t[rt].ch[1]]=rt;
    		del(old);update(rt);
    	}
    	ll pre(ll v){
    		int i=rt;ll maxa=-1;
    		while(i){
    			if(t[i].v==v)return v;
    			if(t[i].v<v){
    				maxa=max(maxa,t[i].v);
    				i=rc;
    			}
    			else i=lc;
    		}
    		return maxa;
    	}
    	ll next(ll v){
    		int i=rt;ll mina=2147483649;
    		while(i){
    			if(t[i].v==v)return v;
    			if(t[i].v>v){
    				mina=min(mina,t[i].v);
    				i=lc;
    			}
    			else i=rc;
    		}
    		return mina;
    	}
    }t1,t2;
    
    inline void solve_1(){
    	ll v=read();
    	if(!t2.rt)  //如果没有另一种数,先存起来
    		t1.insert(v);
    	else{
    		ll pre=t2.pre(v),next=t2.next(v); //查询前后缀,没有前缀则前缀为-1,没有后缀则后缀为2147483649
    		if(pre==-1){
    			ans=(ans+next-v)%mo;
    			t2.earase(next);return;
    		}
    		if(next==2147483649){
    			ans=(ans+v-pre)%mo;
    			t2.earase(pre);return;
    		}
    		if(v-pre<=next-v){   //按照题意取较小,然后删除就可以了
    			ans=(ans+v-pre)%mo;
    			t2.earase(pre);return;
    		}
    		else{
    			ans=(ans+next-v)%mo;
    			t2.earase(next);return;
    		}
    	}
    }
    inline void solve_2(){  //同上
    	ll v=read();
    	if(!t1.rt)
    		t2.insert(v);
    	else{
    		ll pre=t1.pre(v),next=t1.next(v);
    		if(pre==-1){
    			ans=(ans+next-v)%mo;
    			t1.earase(next);return;
    		}
    		if(next==2147483649){
    			ans=(ans+v-pre)%mo;
    			t1.earase(pre);return;
    		}
    		if(v-pre<=next-v){
    			ans=(ans+v-pre)%mo;
    			t1.earase(pre);return;
    		}
    		else{
    			ans=(ans+next-v)%mo;
    			t1.earase(next);return;
    		}
    	}
    }
    
    int main(){
    	n=read();
    	while(n--){
    		int zz=read();
    		switch(zz){
    			case 0:solve_1();break;
    			case 1:solve_2();break;
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    不要抄代码哦

  • 相关阅读:
    Monkeyrunner介绍
    monkeyrunner 简单用例编写
    Android中如何查看内存
    Android内存之VSS/RSS/PSS/USS
    Android内存泄露(全自动篇)
    生成hprof文件,用MAT进行分析
    OpenGL入门学习【转】
    Vim保存代码折叠信息【转】
    windows下Cscope【转】
    Ruby学习笔记:Fiber
  • 原文地址:https://www.cnblogs.com/hanruyun/p/10248973.html
Copyright © 2011-2022 走看看