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

    这是题目链接

    大家好,这个题我调了很久过了,所以想写题解
    我用的平衡树是AVL树,平衡树界的老爷爷
    这个树并不会很慢,主要是我初学,常数巨大
    而且题目的 $ n = 80000$,可以接受

    (solution):

    开两颗平衡树,维护宠物和人,过多就插入自己的平衡树,过少就在对立平衡树中删除与 (x) 相差最小的。

    也就是确定前驱后继

    代码很长,但是操作是相同的,一半都是在复制粘贴

    希望注意传参引用,少写一个调了很长时间

    (code:)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N = 80000+50;
    const int mod = 1000000;
    int ans;
    inline void read(int &k) {
    	k=0;char ch=getchar();
    	while(ch>'9'||ch<'0') ch=getchar();
    	while(ch<='9'&&ch>='0') k=k*10+ch-'0',ch=getchar();
    }
    namespace pet{
    	int root,cnt;
    	struct node{
    		int l,r,val,height,size;
    	}avl[N];
    	inline void newnode(int &now,int val) {
    		avl[now=++cnt].val=val,avl[now].size=1;
    	}
    	int factor(int now) {
    		return avl[avl[now].l].height-avl[avl[now].r].height;
    	}
    	void update(int now) {
    		avl[now].size=avl[avl[now].l].size+avl[avl[now].r].size+1;
    		avl[now].height=max(avl[avl[now].l].height,avl[avl[now].r].height)+1;
    	}
    	void zag(int &now) {
    		int r=avl[now].r;
    		avl[now].r=avl[r].l;
    		avl[r].l=now;
    		now=r;
    		update(avl[now].l),update(now);
    	}
    	void zig(int &now) {
    		int l=avl[now].l;
    		avl[now].l=avl[l].r;
    		avl[l].r=now;
    		now=l;
    		update(avl[now].r),update(now);
    	}
    	void check(int &now) {
    		int bf=factor(now);
    		if(bf>1) {
    			int lf=factor(now);
    			if(lf>0) zig(now);
    			else zag(avl[now].l),zig(now);
    		}else if(bf<-1) {
    			int rf=factor(now);
    			if(rf<0) zag(now);
    			else zig(avl[now].r),zag(now);
    		}else if(now) update(now);
    	}
    	void ins(int &now,int val) {
    		if(!now) newnode(now,val);
    		else if(avl[now].val>val) ins(avl[now].l,val);
    		else ins(avl[now].r,val);
    		check(now);
    	}
    	int find(int &now,int fa) {
    		int tmp;
    		if(!avl[now].l) tmp=now,avl[fa].l=avl[now].r;
    		else tmp=find(avl[now].l,now),check(now);
    		return tmp;
    	}
    	void del(int &now,int val) {
    		if(avl[now].val==val) {
    			int l=avl[now].l,r=avl[now].r;
    			if(!l||!r) now=l+r;
    			else {
    				now=find(r,r);
    				if(now!=r) avl[now].r=r;
    				avl[now].l=l;
    			}
    		}else if(avl[now].val>val) del(avl[now].l,val);
    		else del(avl[now].r,val);
    		check(now);
    	}
    	int getrank(int val) {
    		int now=root,rank=1;
    		while(now) {
    			if(val<=avl[now].val) now=avl[now].l;
    			else rank+=avl[avl[now].l].size+1,now=avl[now].r;
    		}
    		return rank;
    	}
    	int getnum(int rank) {
    		int now=root;
    		while(now) {
    			if(rank==avl[avl[now].l].size+1) break;
    			else if(rank<=avl[avl[now].l].size) now=avl[now].l;
    			else rank-=avl[avl[now].l].size+1,now=avl[now].r;
    		}
    		return avl[now].val;
    	}
    	int search(int now,int val) {
    		if(!now) return false;
    		if(val==avl[now].val) return true;
    		else if(val<avl[now].val) return search(avl[now].l,val);
    		else return search(avl[now].r,val);
    		return false;
    	}
    }
    namespace human{
    	int root,cnt;
    	struct node{
    		int l,r,val,height,size;
    	}avl[N];
    	inline void newnode(int &now,int val) {
    		avl[now=++cnt].val=val,avl[now].size=1;
    	}
    	int factor(int now) {
    		return avl[avl[now].l].height-avl[avl[now].r].height;
    	}
    	void update(int now) {
    		avl[now].size=avl[avl[now].l].size+avl[avl[now].r].size+1;
    		avl[now].height=max(avl[avl[now].l].height,avl[avl[now].r].height)+1;
    	}
    	void zag(int &now) {
    		int r=avl[now].r;
    		avl[now].r=avl[r].l;
    		avl[r].l=now;
    		now=r;
    		update(avl[now].l),update(now);
    	}
    	void zig(int &now) {
    		int l=avl[now].l;
    		avl[now].l=avl[l].r;
    		avl[l].r=now;
    		now=l;
    		update(avl[now].r),update(now);
    	}
    	void check(int &now) {
    		int bf=factor(now);
    		if(bf>1) {
    			int lf=factor(now);
    			if(lf>0) zig(now);
    			else zag(avl[now].l),zig(now);
    		}else if(bf<-1) {
    			int rf=factor(now);
    			if(rf<0) zag(now);
    			else zig(avl[now].r),zag(now);
    		}else if(now) update(now);
    	}
    	void ins(int &now,int val) {
    		if(!now) newnode(now,val);
    		else if(avl[now].val>val) ins(avl[now].l,val);
    		else ins(avl[now].r,val);
    		check(now);
    	}
    	int find(int &now,int fa) {
    		int tmp;
    		if(!avl[now].l) tmp=now,avl[fa].l=avl[now].r;
    		else tmp=find(avl[now].l,now),check(now);
    		return tmp;
    	}
    	void del(int &now,int val) {
    		if(avl[now].val==val) {
    			int l=avl[now].l,r=avl[now].r;
    			if(!l||!r) now=l+r;
    			else {
    				now=find(r,r);
    				if(now!=r) avl[now].r=r;
    				avl[now].l=l;
    			}
    		}else if(avl[now].val>val) del(avl[now].l,val);
    		else del(avl[now].r,val);
    		check(now);
    	}
    	int getrank(int val) {
    		int now=root,rank=1;
    		while(now) {
    			if(val<=avl[now].val) now=avl[now].l;
    			else rank+=avl[avl[now].l].size+1,now=avl[now].r;
    		}
    		return rank;
    	}
    	int getnum(int rank) {
    		int now=root;
    		while(now) {
    			if(rank==avl[avl[now].l].size+1) break;
    			else if(rank<=avl[avl[now].l].size) now=avl[now].l;
    			else rank-=avl[avl[now].l].size+1,now=avl[now].r;
    		}
    		return avl[now].val;
    	}
    	int search(int now,int val) {
    		if(!now) return false;
    		if(val==avl[now].val) return true;
    		else if(val<avl[now].val) return search(avl[now].l,val);
    		else return search(avl[now].r,val);
    		return false;
    	}
    }
    signed main() {
    	int n; cin>> n;
    	while(n--) {
    		int opt, x;
    //		scanf("%lld%lld",&opt, &x);
    		read(opt),read(x);
    		if(!opt) {
    			if(human::avl[human::root].size) {
    				if(human::search(human::root,x)) human::del(human::root,x);
    				else {
    					int pre=human::getnum(human::getrank(x)-1);
    					int nxt=human::getnum(human::getrank(x+1));
    					if(pre==0) { ans+=nxt-x,ans%=mod,human::del(human::root,nxt);continue;}
    					if(nxt==0) { ans+=x-pre,ans%=mod,human::del(human::root,pre);continue;}					
    					if(x-pre<=nxt-x) ans+=x-pre,ans%=mod,human::del(human::root,pre);
    					else ans+=nxt-x,ans%=mod,human::del(human::root,nxt);
    				}
    			}else pet::ins(pet::root,x);
    		}else {
    			if(pet::avl[pet::root].size) {
    				if(pet::search(pet::root,x)) pet::del(pet::root,x);
    				else {
    					int pre=pet::getnum(pet::getrank(x)-1);
    					int nxt=pet::getnum(pet::getrank(x+1));
    					if(pre==0) { ans+=nxt-x,ans%=mod,pet::del(pet::root,nxt);continue;}
    					if(nxt==0) { ans+=x-pre,ans%=mod,pet::del(pet::root,pre);continue;}
    					if(x-pre<=nxt-x) ans+=x-pre,ans%=mod,pet::del(pet::root,pre);
    					else ans+=nxt-x,ans%=mod,pet::del(pet::root,nxt);
    				}
    			}else human::ins(human::root,x);			
    		}
    	}
    	cout<<ans;	
    	return 0;
    }
    
  • 相关阅读:
    csp-s模拟110
    csp-s模拟109
    留念
    csp-s 2019 游记
    HEOI2020
    CSP-S2019记
    堆积的$TIPS$
    低错复习
    倍增并查集
    4.26
  • 原文地址:https://www.cnblogs.com/skkyk/p/12079930.html
Copyright © 2011-2022 走看看