[HNOI2004]宠物收养所
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以后的结果。
Splay解法+疯狂的暴力对拍
建立两棵伸展树,一棵放宠物,一棵放领养者,可知任意时刻两棵树必有一棵为空树。
删除时比较麻烦,要考虑是否存在pre和next.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<cstdlib> 7 #include<fstream> 8 using namespace std; 9 //ifstream fin("fin.in"); 10 //ofstream fout("test.out"); 11 12 long long n,ans=0; 13 typedef struct{ 14 int tot,root,key[100000],pre[100000],ch[100000][2]; 15 }Node; 16 Node N[2]; 17 18 void Newnode(int k,int &num,int father,int d){ 19 num=++N[k].tot;N[k].key[num]=d;N[k].pre[num]=father; 20 N[k].ch[num][0]=N[k].ch[num][1]=0;return ; 21 } 22 23 void Rotate(int k,int x,int kind){ 24 int y=N[k].pre[x]; 25 N[k].ch[y][!kind]=N[k].ch[x][kind]; 26 N[k].pre[N[k].ch[y][!kind]]=y; 27 28 if(N[k].pre[y]) N[k].ch[N[k].pre[y]][y==N[k].ch[N[k].pre[y]][1]]=x; 29 N[k].pre[x]=N[k].pre[y]; 30 31 32 N[k].pre[y]=x; 33 N[k].ch[x][kind]=y; 34 35 return ; 36 } 37 38 void Splay(int k,int x,int goal){ 39 while(N[k].pre[x]!=goal) 40 { 41 int y=N[k].pre[x]; 42 if(N[k].pre[y]==goal) Rotate(k,x,N[k].ch[y][0]==x); 43 else 44 { 45 int z=N[k].pre[y];int kind=N[k].ch[z][0]==y; 46 if(N[k].ch[y][!kind]==x) {Rotate(k,y,kind);Rotate(k,x,kind);} 47 else {Rotate(k,x,!kind);Rotate(k,x,kind);} 48 } 49 } 50 N[k].root=x;return ; 51 52 } 53 54 int Insert(int k,int d){//return 1 则找到相等于d的节点 55 if(N[k].root==0) {Newnode(k,N[k].root,0,d);return 0;}// 56 int x=N[k].root; 57 while(N[k].ch[x][N[k].key[x]<d]) 58 { 59 if(N[k].key[x]==d) {Splay(k,x,0);return 1;} 60 x=N[k].ch[x][N[k].key[x]<d]; 61 } 62 if(N[k].key[x]==d) {Splay(k,x,0);return 1;} 63 64 Newnode(k,N[k].ch[x][N[k].key[x]<d],x,d); 65 Splay(k,N[k].ch[x][N[k].key[x]<d],0); 66 return 0; 67 } 68 69 int Pre(int k,int root){ 70 if(N[k].ch[root][0]==0) return 0; 71 int x=N[k].ch[root][0]; 72 while(N[k].ch[x][1]) 73 x=N[k].ch[x][1]; 74 return x; 75 } 76 77 int Next(int k,int root){ 78 if(N[k].ch[root][1]==0) return 0; 79 int x=N[k].ch[root][1]; 80 while(N[k].ch[x][0]) 81 x=N[k].ch[x][0]; 82 return x; 83 } 84 85 86 int a,b; 87 void Change(int k,int c){ //删除root,splay c 88 int y=N[k].ch[N[k].root][1]; 89 N[k].ch[a][1]=y; 90 N[k].pre[y]=a; 91 92 N[k].root=N[k].ch[N[k].root][0]; 93 N[k].pre[N[k].root]=0; 94 95 Splay(k,c,0); 96 } 97 int Union(int k,int d){//合并root的两子树,并求值 98 a=Pre(k,N[k].root); 99 b=Next(k,N[k].root); 100 101 //cout<<N[k] 102 103 // cout<<"pre "<<N[k].key[a]<<endl; 104 // cout<<"next "<<N[k].key[b]<<endl; 105 if(a==0) 106 { 107 ans+=abs(N[k].key[b]-d);ans%=1000000; 108 // N[k].ch[N[k].pre[b]][N[k].key[N[k].pre[b]]<N[k].key[b]]=0; 109 N[k].root=N[k].ch[N[k].root][1]; 110 N[k].pre[N[k].root]=0; 111 Splay(k,b,0); 112 N[k].root=N[k].ch[N[k].root][1]; 113 N[k].pre[N[k].root]=0; 114 return 0; 115 } 116 else if(b==0) 117 { 118 ans+=abs(N[k].key[a]-d);ans%=1000000; 119 //N[k].ch[N[k].pre[a]][N[k].key[N[k].pre[a]]<N[k].key[a]]=0; 120 N[k].root=N[k].ch[N[k].root][0]; 121 N[k].pre[N[k].root]=0; 122 Splay(k,a,0); 123 N[k].root=N[k].ch[N[k].root][0]; 124 N[k].pre[N[k].root]=0; 125 return 0; 126 } 127 else 128 { 129 ans+=min(abs(N[k].key[a]-d),abs(N[k].key[b]-d));ans%=1000000; 130 if((abs(N[k].key[a]-d)==abs(N[k].key[b]-d)&&N[k].key[a]<N[k].key[b])||abs(N[k].key[a]-d)<abs(N[k].key[b]-d)) 131 {Change(k,a);return 1;}///splay a,删除a 132 else {Change(k,b);return 1;} 133 } 134 } 135 136 void Print(int k,int x){ 137 cout<<N[k].key[x]<<" "<<N[k].key[N[k].pre[x]]<<endl; 138 if(N[k].ch[x][0]) Print(k,N[k].ch[x][0]); 139 if(N[k].ch[x][1]) Print(k,N[k].ch[x][1]); 140 } 141 142 void Delete(int k,int d){ 143 if(Insert(k,d)) 144 { 145 a=Pre(k,N[k].root); 146 if(a==0) 147 { 148 N[k].root=N[k].ch[N[k].root][1]; 149 N[k].pre[N[k].root]=0; 150 } 151 else 152 Change(k,a); 153 154 return ; 155 } 156 157 // cout<<"k "<<k<<" "<<d<<endl; 158 // Print(k,N[k].root); 159 // 160 if(Union(k,d)) 161 { 162 a=Pre(k,N[k].root); 163 if(a==0) 164 { 165 N[k].root=N[k].ch[N[k].root][1]; 166 N[k].pre[N[k].root]=0; 167 } 168 else 169 Change(k,a); 170 } 171 //cout<<ans<<" ans"<<endl; 172 } 173 174 int main() 175 { 176 cin>>n; 177 N[0].tot=N[1].tot=N[0].root=N[1].root=0; 178 179 for(int i=1;i<=n;++i) 180 { 181 int x,y; 182 cin>>x>>y; 183 184 if(x==0) {if(N[1].root==0) Insert(0,y);else Delete(1,y);} 185 if(x==1) {if(N[0].root==0) Insert(1,y);else {Delete(0,y);}}//Print(0,N[0].root); 186 // cout<<N[0].root<<" "<<N[1].root<<endl; 187 // cout<<ans<<endl; 188 } 189 190 cout<<ans<<endl; 191 // system("pause"); 192 return 0; 193 194 }