[HNOI2004]宠物收养场

# [[HNOI2004]宠物收养场 ](https://www.cnblogs.com/LeagueofLegends2004/articles/10312090.html ) [洛谷链接](https://www.luogu.org/problemnew/show/P2286)

  这是一道比较简单的题目,一眼便可以看出来是一道很水的平衡树的题。想要解决此题首先就要至少会写一种平衡树,当然这道题用不到平衡树的所有操作,只有插入、删除、前驱、后继操作。由于作者太菜了只会使用常数巨大的splay,想必各位巨佬们一定用是红黑树之类的。

Solution

  一种比较蠢的做法是开两棵splay(其实正解一个就够了),一棵用来存领养者的信息记为b,另一棵用来存宠物的信息记为a。当进来的进来的是宠物时,分两种情况。1.如果没有领养者,那么可以直接将宠物加入平衡树a中;2.如果有领养者,那么只要拿着这个宠物的特点值在平衡树b中去匹配一下(即找一下它的前驱和后继)。如果进来的是领养者就做相反的处理,然后就可以愉快地AC这道题了。时间复杂的是\(O(nlog_2n)\),对于80000的输入数据随便过。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define N 100005
#define mod 1000000 
#define ll long long 
#define rint register int
using namespace std; 
inline char get(){	const int TOP=1000000;
    static char T[TOP],*x=T,*y=T;
    return x==y&&(y=(x=T)+fread(T,1,TOP,stdin),x==y)?EOF:*x++;
}
inline int read (){
    register int num,sign=1;register char c;
    while (((c=get())<'0'||c>'9')&&c!='-');c=='-'?num=sign=0:num=c-48;
    while ((c=get())>='0'&&c<='9')num=(num<<3)+(num<<1)+(c-48);
    return sign?num:-num;
}
class Tree{
public:
    int root,len,S;
    int f[N],r[N],l[N],data[N],cnt[N];
    inline void rotate(rint x){
        rint y=f[x],z=f[f[x]];
        if(l[z]==y)l[z]=x;else r[z]=x;f[x]=z;
        if(l[y]==x){l[y]=r[x];f[r[x]]=y;r[x]=y;f[y]=x;}else {r[y]=l[x];f[l[x]]=y;l[x]=y;f[y]=x;}
        l[0]=r[0]=0;
    }
    inline void splay(rint x,rint rt){
        for(;f[x]!=rt;rotate(x)){
            rint y=f[x],z=f[f[x]];
                if(z==rt)continue;
            rotate((l[y]==x)^(l[z]==y)?x:y);
        }
        if(rt==0)root=x;
    }
    inline int find_pre(rint x){
        rint u=root,res=-1;;
        while(u){
            if(data[u]<x&&(res==-1||data[u]>data[res]))res=u;
            u=x<=data[u]?l[u]:r[u];
        }
        return res;
    }
    inline int find_sub(rint x){
        rint u=root,res=-1;
            while(u){
            if(data[u]>x&&(res==-1||data[u]<data[res]))res=u;
            u=x<data[u]?l[u]:r[u];
        }
        return res;
    }
    inline int find(rint x){
        rint u=root,res=-1;
        while(u&&data[u]!=x)u=x<data[u]?l[u]:r[u];
        return u;
    }
    inline void insert(rint x){
        rint u=root,fa=0;
        while(u&&data[u]!=x){fa=u;u=x<data[u]?l[u]:r[u];}
        if(u)cnt[u]++;
        else{u=++len;
            cnt[u]=1;data[u]=x;f[u]=fa;l[u]=r[u]=0; 	
            if(x<data[fa])l[fa]=u;else r[fa]=u;
        }
        splay(u,0);S++;
    }
    inline void erase(rint x){
        rint s=find_sub(x),p=find_pre(x);
        splay(p,0);splay(s,p);
        if(cnt[l[s]]>1){--cnt[l[s]];splay(l[s],0);return;}
        l[s]=0;f[l[s]]=0;--S;
    }		
}a,b;
int n,x,y;
ll ans;
int main(){
    n=read();
    a.insert(2147483647);a.insert(-2147483647);
    b.insert(2147483647);b.insert(-2147483647);
    for(rint i=1;i<=n;++i){
        x=read();y=read();
        if(!x){
            if(b.S>2){
                if(!b.find(y)){
                    ll p=b.data[b.find_pre(y)],s=b.data[b.find_sub(y)];
                    if(abs(p-y)<abs(s-y))ans=(ans+abs(p-y))%mod,b.erase(p);
                    else ans=(ans+abs(s-y))%mod,b.erase(s);
                }else a.erase(b.find(y));
            }
            else a.insert(y);
        }else{
            if(a.S>2){
                if(!a.find(y)){
                    ll p=a.data[a.find_pre(y)],s=a.data[a.find_sub(y)];
                    if(abs(p-y)<=abs(s-y))ans=(ans+abs(p-y))%mod,a.erase(p);
                    else ans=(ans+s-y)%mod,a.erase(s);
                }else a.erase(a.find(y));
            }else b.insert(y);
        }
    }
    printf("%d\n",ans);
}

posted @ 2019-01-23 23:31  利姆鲁·特恩佩斯特  阅读(110)  评论(0)    收藏  举报