[HNOI2004]寵物收養場
阿新 • • 發佈:2019-04-03
直接插入 正整數 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]寵物收養場