1. 程式人生 > >[HNOI2004]寵物收養場

[HNOI2004]寵物收養場

直接插入 正整數 getc www. 選擇 初始 bits 也有 noi

洛咕

題意:寵物收養場提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物.每個領養者都希望領養到自己滿意的寵物,每個領養者希望領養的寵物的特點值為a(a是一個正整數,a<2^31),而每個處在收養場的寵物也有一個特點值.

寵物收養場總是會有兩種情況發生:被遺棄的寵物過多或者是想要收養寵物的人太多,而寵物太少.

被遺棄的寵物過多時,假若到來一個領養者,這個領養者希望領養的寵物的特點值為a,那麽它將會領養一只目前未被領養的寵物中特點值最接近a的一只寵物。(任何兩只寵物的特點值都不可能是相同的,任何兩個領養者的希望領養寵物的特點值也不可能是一樣的)如果有兩只滿足要求的寵物,即存在兩只寵物他們的特點值分別為a-b和a+b,那麽領養者將會領養特點值為a-b的那只寵物。

收養寵物的人過多,假若到來一只被收養的寵物,那麽能夠領養它的領養者,是那個希望被領養寵物的特點值最接近該寵物特點值的領養者,如果該寵物的特點值為a,存在兩個領養者他們希望領養寵物的特點值分別為a-b和a+b,那麽特點值為a-b的那個領養者將成功領養該寵物。

(這兩段的意思就是對於一個數x,找它的前驅和後繼,如果前驅和後繼與x的差值恰好相等,則選擇前驅,否則選擇差值較小的)

一個領養者領養了一個特點值為a的寵物,而它本身希望領養的寵物的特點值為b,那麽這個領養者的不滿意程度為abs(a-b)。你得到了一年當中,領養者和被收養寵物到來收養所的情況,請你計算所有收養了寵物的領養者的不滿意程度的總和。這一年初始時,收養所裏面既沒有寵物,也沒有領養者.

分析:平衡樹部分是裸模板,但是有一個細節,就是寵物樹和領養者樹之間的轉換.bj=0,1,2分別表示寵物樹,領養者樹,中立樹.顯然一開始是中立樹.

如果當前是寵物樹bj=0(即寵物過多時),來一個寵物就直接插入樹中,來一個領養者,直接查詢前驅後繼拿走一個寵物,當樹中最後一個寵物被領走時,bj=2表示樹是中立的.

如果當前是領養者樹bj=1(即領養者過多時),來一個領養者就直接插入樹中,來一個寵物,直接查詢前驅後繼刪除一個領養者,當樹中最後一個領養者離開時,bj=2表示樹是中立的.

bj=2時,如果當前插入一個寵物則bj=0,否則bj=1;

#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
#define MAXN 100005
using namespace std;
inline int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
const int mod=1000000;
int p,tot,bj=2;LL ans;
int size[MAXN],num[MAXN],val[MAXN],rd[MAXN];
int son[MAXN][2];
void pushup(int p){size[p]=size[son[p][0]]+size[son[p][1]]+num[p];}
void rotate(int &p,int d){
    int k=son[p][d^1];
    son[p][d^1]=son[k][d];
    son[k][d]=p;
    pushup(p);pushup(k);p=k;
    return;
}
void Insert(int &p,int x){
    if(!p){
        p=++tot;size[p]=num[p]=1;
        val[p]=x;rd[p]=rand();
        return;
    }
    if(val[p]==x){
        size[p]++;num[p]++;
        return;
    }
    int d=(val[p]<x);Insert(son[p][d],x);
    if(rd[p]<rd[son[p][d]])rotate(p,d^1);
    pushup(p);return;
}
void Delete(int &p,int x){
    if(!p)return;
    else if(val[p]<x)Delete(son[p][1],x);
    else if(val[p]>x)Delete(son[p][0],x);
    else{
        if(!son[p][0]&&!son[p][1]){
            size[p]--;num[p]--;
            if(size[p]==0)p=0;
        }
        else if(!son[p][0]&&son[p][1]){
            rotate(p,0);
            Delete(son[p][0],x);
        }
        else if(son[p][0]&&!son[p][1]){
            rotate(p,1);
            Delete(son[p][1],x);
        }
        else if(son[p][0]&&son[p][1]){
            int d=(rd[son[p][0]]>rd[son[p][1]]);
            rotate(p,d);Delete(son[p][d],x);
        }
    }
    pushup(p);
}
int pre(int p,int x){
    if(!p)return -INF;
    else if(val[p]>=x)return pre(son[p][0],x);
    else return max(val[p],pre(son[p][1],x));
}
int nxt(int p,int x){
    if(!p)return INF;
    else if(val[p]<=x)return nxt(son[p][1],x);
    else return min(val[p],nxt(son[p][0],x));
}
int main(){
    int n=read();
    while(n--){
        int opt=read(),x=read();
        if(opt==0){
            if(bj==0)Insert(p,x);
            else if(bj==1){
                LL ans1=pre(p,x),ans2=nxt(p,x);
                if(ans1==-INF&&ans2==INF)continue;
                else if(ans1==-INF&&ans2!=INF){
                    ans+=ans2-x;Delete(p,ans2);
                }
                else if(ans1!=-INF&&ans2==INF){
                    ans+=x-ans1;Delete(p,ans1);
                }
                else if((ans2-x)<(x-ans1))ans+=ans2-x,Delete(p,ans2);
                else ans+=x-ans1,Delete(p,ans1);
            }
            else if(bj==2)Insert(p,x),bj=0;
            if(p==0)bj=2;
        }
        else{
            if(bj==0){
                LL ans1=pre(p,x),ans2=nxt(p,x);
                if(ans1==-INF&&ans2==INF)continue;
                else if(ans1==-INF&&ans2!=INF){
                    ans+=ans2-x;Delete(p,ans2);
                }
                else if(ans1!=-INF&&ans2==INF){
                    ans+=x-ans1;Delete(p,ans1);
                }
                else if((ans2-x)<(x-ans1))ans+=ans2-x,Delete(p,ans2);
                else ans+=x-ans1,Delete(p,ans1);
            }
            else if(bj==1)Insert(p,x);
            else if(bj==2)Insert(p,x),bj=1;
            if(p==0)bj=2;
        }
        ans=(ans+mod)%mod;  
    }
    printf("%lld\n",ans);
    return 0;
}

[HNOI2004]寵物收養場