1. 程式人生 > >bzoj1208: [HNOI2004]寵物收養所

bzoj1208: [HNOI2004]寵物收養所

hint a+b ota 情況 led 們的 發生 超過 描述

1208: [HNOI2004]寵物收養所

Time Limit: 10 Sec Memory Limit: 162 MB

Description

最近,阿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)。【任務描述】你得到了一年當中,領養者和被收養寵物到來收養所的情況,希望你計算所有收養了寵物的領養者的不滿意程度的總和。這一年初始時,收養所裏面既沒有寵物,也沒有領養者。

Input

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

Output

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

Sample Input

5
0 2
0 4
1 3
1 2
1 5

Sample Output

3
(abs(3-2) + abs(2-4)=3,最後一個領養者沒有寵物可以領養)

HINT

Source

Splay題,思路不難,寫起來煩,多寫寫就好了;

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #define MOD 1000000
  6 using namespace std;
  7  
  8 const int MAXN=200008;
  9 int n,m,num[MAXN],tree[MAXN][2],t1,t2,kind,size,rt,fa[MAXN];
 10 long
long ans; 11 12 void rotate(int x,int &k){ 13 int y=fa[x],z=fa[y],l,r; 14 if(y==k) k=x; 15 else{ 16 if(tree[z][0]==y) tree[z][0]=x; else tree[z][1]=x; 17 } 18 if(tree[y][0]==x) l=0; else l=1; 19 r=l^1; 20 fa[x]=z; fa[y]=x; fa[tree[x][r]]=y; 21 tree[y][l]=tree[x][r]; tree[x][r]=y; 22 } 23 24 void splay(int x,int &k){ 25 int y,z; 26 while(x!=k){ 27 y=fa[x]; z=fa[y]; 28 if(y!=k){ 29 if((tree[y][0]==x)^(tree[z][0]==y)) rotate(x,k); 30 else rotate(y,k); 31 } 32 rotate(x,k); 33 } 34 } 35 36 void insert(int &k,int x,int last){ 37 if(k==0){ 38 size++; 39 k=size; 40 num[k]=x; 41 fa[k]=last; 42 splay(k,rt); 43 return; 44 } 45 if(x>num[k]) insert(tree[k][1],x,k); 46 else insert(tree[k][0],x,k); 47 } 48 49 void ask_after(int k,int x){ 50 if(k==0) return; 51 if(num[k]>=x){ 52 t2=k; 53 ask_after(tree[k][0],x); 54 }else{ 55 ask_after(tree[k][1],x); 56 } 57 } 58 59 void ask_before(int k,int x){ 60 if(k==0) return; 61 if(num[k]<=x){ 62 t1=k; 63 ask_before(tree[k][1],x); 64 }else{ 65 ask_before(tree[k][0],x); 66 } 67 } 68 69 void del(int x){ 70 splay(x,rt); 71 if(tree[x][0]*tree[x][1]==0) 72 rt=tree[x][0]+tree[x][1]; 73 else{ 74 int t=tree[x][1]; 75 while(tree[t][0]) t=tree[t][0]; 76 tree[t][0]=tree[x][0]; 77 fa[tree[x][0]]=t; 78 rt=tree[x][1]; 79 } 80 fa[rt]=0; 81 } 82 83 int main(){ 84 scanf("%d",&n); 85 kind=0; ans=0; 86 for(int i=1;i<=n;i++){ 87 int x,f; 88 scanf("%d%d",&f,&x); 89 if(!rt){kind=f;insert(rt,x,0);} 90 else{ 91 if(kind==f){insert(rt,x,0);} 92 else{ 93 t1=-1; t2=-1; 94 ask_before(rt,x); 95 ask_after(rt,x); 96 if(t2==-1){ ans=(ans+x-num[t1])%MOD;del(t1);} 97 else{ 98 if(t1==-1){ ans=(ans+num[t2]-x)%MOD;del(t2);} 99 else{ 100 if(x-num[t1]>num[t2]-x){ ans=(ans+num[t2]-x)%MOD;del(t2);} 101 else { ans=(ans+x-num[t1])%MOD;del(t1);} 102 } 103 } 104 } 105 } 106 } 107 printf("%lld",ans); 108 }

bzoj1208: [HNOI2004]寵物收養所