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;
    }
    

    不要抄代码哦

  • 相关阅读:
    Attributes in C#
    asp.net C# 时间格式大全
    UVA 10518 How Many Calls?
    UVA 10303 How Many Trees?
    UVA 991 Safe Salutations
    UVA 10862 Connect the Cable Wires
    UVA 10417 Gift Exchanging
    UVA 10229 Modular Fibonacci
    UVA 10079 Pizza Cutting
    UVA 10334 Ray Through Glasses
  • 原文地址:https://www.cnblogs.com/hanruyun/p/10248973.html
Copyright © 2011-2022 走看看