1. 程式人生 > >HNOI2004寵物收養所(splay維護二叉搜索樹模板題)

HNOI2004寵物收養所(splay維護二叉搜索樹模板題)

個數 正整數 noi 模板題 sea () clu search 公式

描述

最近,阿Q開了一間寵物收養所。收養所提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物。每個領養者都希望領養到自己滿意的寵物,阿Q根據領養者的要求通過他自己發明的一個特殊的公式,得出該領養者希望領養的寵物的特點值a(a是一個正整數,a<2^31),而他也給每個處在收養所的寵物一個特點值。這樣他就能夠很方便的處理整個領養寵物的過程了,寵物收養所總是會有兩種情況發生:被遺棄的寵物過多或者是想要收養寵物的人太多,而寵物太少。 1. 被遺棄的寵物過多時,假若到來一個領養者,這個領養者希望領養的寵物的特點值為a,那麽它將會領養一只目前未被領養的寵物中特點值最接近a的一只寵物。(任何兩只寵物的特點值都不可能是相同的,任何兩個領養者的希望領養寵物的特點值也不可能是一樣的)如果有兩只滿足要求的寵物,即存在兩只寵物他們的特點值分別為a-b和a+b,那麽領養者將會領養特點值為a-b的那只寵物。 2. 收養寵物的人過多,假若到來一只被收養的寵物,那麽哪個領養者能夠領養它呢?能夠領養它的領養者,是那個希望被領養寵物的特點值最接近該寵物特點值的領養者,如果該寵物的特點值為a,存在兩個領養者他們希望領養寵物的特點值分別為a-b和a+b,那麽特點值為a-b的那個領養者將成功領養該寵物。 一個領養者領養了一個特點值為a的寵物,而它本身希望領養的寵物的特點值為b,那麽這個領養者的不滿意程度為abs(a-b)。【任務描述】你得到了一年當中,領養者和被收養寵物到來收養所的情況,希望你計算所有收養了寵物的領養者的不滿意程度的總和。這一年初始時,收養所裏面既沒有寵物,也沒有領養者。

輸入格式

第一行為一個正整數n,n<=80000,表示一年當中來到收養所的寵物和領養者的總數。接下來的n行,按到來時間的先後順序描述了一年當中來到收養所的寵物和領養者的情況。每行有兩個正整數a, b,其中a=0表示寵物,a=1表示領養者,b表示寵物的特點值或是領養者希望領養寵物的特點值。(同一時間呆在收養所中的,要麽全是寵物,要麽全是領養者,這些寵物和領養者的個數不會超過10000個)

輸出格式

僅有一個正整數,表示一年當中所有收養了寵物的領養者的不滿意程度的總和mod 1000000以後的結果。

測試樣例

輸入

5 0 2
0 4
1 3
1 2
1 5

輸出

3 一道splay維護二叉搜索樹的題。我寫的這個splay有些常數略大
插入元素:從根節點向下找到這個數的位置直到找到一個空節點,就插入。 刪除元素:將這個點轉到根節點,判斷一下是否為當前剩余元素中的最值,如果是的話就直接刪除,否則就找到他的前驅(即根的左子樹中最大的一個),將前驅的值賦給他然後將前驅刪掉。 尋找元素:按照二叉搜索樹的性質一直往下搜即可。 技巧: 在插入元素的時候,如果這個節點過深,那麽久強行旋轉一下這個點到根節點使得這條鏈形態改變。(結果發現跑的巨快......)。 代碼如下:
#include<algorithm>
#include<iostream>
#include<cstring>
#include
<cstdio> #include<cmath> #define LL long long #define mod 1000000 #define M 80010 using namespace std; LL read(){ LL nm=0,oe=1;char cw=getchar(); while(!isdigit(cw)) oe=cw==-?-oe:oe,cw=getchar(); while(isdigit(cw)) nm=nm*10+(cw-0),cw=getchar(); return nm*oe; } LL n,m,ans,T,tpe,t,w; struct binary_search_tree{ LL ace,l[M],r[M],p[M],cnt,tp[M],sz; void init(){l[0]=r[0]=cnt=ace=sz=0,p[0]=tp[0];} void rotate(LL x){ if(ace==x) return; LL top=tp[x]; if(ace==top) tp[ace]=x,ace=x; else{ if(l[tp[top]]==top) l[tp[top]]=x; else r[tp[top]]=x; tp[x]=tp[top],tp[top]=x; } if(l[top]==x) l[top]=r[x],tp[r[x]]=top,r[x]=top; else r[top]=l[x],tp[l[x]]=top,l[x]=top; } void splay(LL x){ if(x==0) return; while(ace!=x){ LL k=tp[x]; if(k==ace) rotate(x); else if(l[l[tp[k]]]==x||r[r[tp[k]]]==x) rotate(k); else rotate(x); } return; } void del(LL x){ sz--; if(x==0){return;} splay(x); if(l[x]==0&&r[x]==0){init();return;} if(l[x]==0) ace=r[x]; else if(r[x]==0) ace=l[x]; else{ LL k=l[x]; if(r[k]==0){l[ace]=l[k],tp[l[k]]=ace,p[ace]=p[k];return;} while(r[k]!=0) k=r[k]; r[tp[k]]=l[k],tp[l[k]]=tp[k],p[ace]=p[k]; } } void insert(LL x){ sz++; if(ace==0){p[++cnt]=x,ace=cnt,l[cnt]=r[cnt]=0;return;} LL pos=ace,big=0; while(pos!=0){ if(p[pos]<=x){ if(r[pos]==0){r[pos]=++cnt,p[cnt]=x,tp[cnt]=pos;break;} pos=r[pos]; } else{ if(l[pos]==0){l[pos]=++cnt,p[cnt]=x,tp[cnt]=pos;break;} pos=l[pos]; } big++; } l[cnt]=r[cnt]=0; if(big>=30) splay(cnt); } LL find(LL x){ LL k=ace,len=99999999999999ll,num=ace; while(true){ if(k==0) break; if(p[k]==x) return k; if(p[k]>x){ if(len>p[k]-x) len=p[k]-x,num=k; k=l[k]; } else{ if(len>=x-p[k]) len=x-p[k],num=k; k=r[k]; } } return num; } }pet,hum; LL ab(LL x){return x>0?x:-x;} int main(){ pet.init(),hum.init(); T=read(); while(T--){ tpe=read(),t=read(); if(tpe==0){ if(hum.ace==0) pet.insert(t); else{ w=hum.find(t); ans+=ab(t-hum.p[w]); hum.del(w); } } else{ if(pet.ace==0) hum.insert(t); else{ w=pet.find(t); ans+=ab(t-pet.p[w]); pet.del(w); } } } printf("%lld\n",ans%mod); return 0; }


HNOI2004寵物收養所(splay維護二叉搜索樹模板題)