BZOJ 1208 [HNOI2004]宠物收养所:Splay(伸展树)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1208
题意:
有一个宠物收养所,在接下来一段时间内会陆续有一些宠物进到店里,或是一些人来领养宠物。宠物和人的总数量为n。
t = 0代表宠物,t = 1代表人。
宠物和人分别有一个特点值a和b。有两种情况:
(1)店里全是宠物,这时进来一个人来领养宠物。那么他会领养走abs(a-b)最小的那只宠物(b = a - x or a + x)。
如果使得abs(a-b)最小的有不止一只宠物,那么b = a - x的那只会被领养走。
(2)店里全是等待的人。这事有一只宠物被送进店里,那么它会被abs(a-b)最小的那个人领养走(a = b - x or b + x)。
如果使得abs(a-b)最小的不只有一个人,那么宠物会被a = b - x的人领养走。
按照依次来到店里的顺序,给出a,b。
a = 0代表宠物,a = 1代表人。b为对应的特点值。
定义每一次领养的不满意度 = abs(宠物特点值 - 人的特点值)
问你所有不满意度之和 MOD 1000000。
题解:
Splay。
分析:
(1)在每一个时刻(除了正在领养),店里要么全是宠物,要么全是人,要么为空。
(2)在本题中,除了只能是人和宠物匹配这个特性,人和宠物是等价的,都可以在店里等待。
(3)有可能先进来一大堆宠物,再进来一大堆人。这时搜索树会退化成链,所以要用splay。
实现:
每输入一对a,b:
(1)如果店为空,那么将东西加入树中,并将树的类型改为a。
(2)如果进来一个同类,那么将当前东西加入树中。
(3)如果进来一个异类,那么找出对于这个异类的特点值的前驱pre与后继suc(类型均为pair<int,int>(dif,idx))。
将被删除的东西为res = min(pre,suc)。
所以erase(res.second),并更新答案ans = (ans + res.first) % MOD。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 80005 5 #define MOD 1000000 6 #define INF 100000000 7 8 using namespace std; 9 10 int n,a,b; 11 int ans=0; 12 int type; 13 int siz=0; 14 int tot=0; 15 int root=-1; 16 int dat[MAX_N]; 17 int par[MAX_N]; 18 int lson[MAX_N]; 19 int rson[MAX_N]; 20 21 void rotate(int x,int type,int *lson,int *rson) 22 { 23 if(type==1) swap(lson,rson); 24 int y=par[x]; 25 int z=par[y]; 26 lson[y]=rson[x]; 27 if(rson[x]!=-1) par[rson[x]]=y; 28 par[x]=z; 29 if(z!=-1) 30 { 31 if(lson[z]==y) lson[z]=x; 32 else rson[z]=x; 33 } 34 rson[x]=y; 35 par[y]=x; 36 } 37 38 void splay(int x,int act) 39 { 40 while(par[x]!=act) 41 { 42 int y=par[x]; 43 int z=par[y]; 44 if(z==act) 45 { 46 if(lson[y]==x) rotate(x,0,lson,rson); 47 else rotate(x,1,lson,rson); 48 } 49 else 50 { 51 if(lson[z]==y && lson[y]==x) 52 { 53 rotate(y,0,lson,rson); 54 rotate(x,0,lson,rson); 55 } 56 if(rson[z]==y && rson[y]==x) 57 { 58 rotate(y,1,lson,rson); 59 rotate(x,1,lson,rson); 60 } 61 if(rson[z]==y && lson[y]==x) 62 { 63 rotate(x,0,lson,rson); 64 rotate(x,1,lson,rson); 65 } 66 if(lson[z]==y && rson[y]==x) 67 { 68 rotate(x,1,lson,rson); 69 rotate(x,0,lson,rson); 70 } 71 } 72 } 73 if(act==-1) root=x; 74 } 75 76 int find(int val) 77 { 78 int now=root; 79 while(now!=-1) 80 { 81 if(val==dat[now]) return now; 82 if(val<dat[now]) now=lson[now]; 83 if(val>dat[now]) now=rson[now]; 84 } 85 return -1; 86 } 87 88 void new_node(int val,int p,int &kid) 89 { 90 dat[tot]=val; 91 par[tot]=p; 92 lson[tot]=-1; 93 rson[tot]=-1; 94 kid=tot; 95 splay(tot,-1); 96 tot++; 97 } 98 99 void insert(int val) 100 { 101 siz++; 102 if(root==-1) 103 { 104 int temp; 105 root=tot; 106 new_node(val,-1,temp); 107 return; 108 } 109 int now=root; 110 while(1) 111 { 112 if(val==dat[now]) return; 113 if(val<dat[now]) 114 { 115 if(lson[now]==-1) 116 { 117 new_node(val,now,lson[now]); 118 return; 119 } 120 else now=lson[now]; 121 } 122 if(val>dat[now]) 123 { 124 if(rson[now]==-1) 125 { 126 new_node(val,now,rson[now]); 127 return; 128 } 129 else now=rson[now]; 130 } 131 } 132 } 133 134 void erase(int x) 135 { 136 siz--; 137 splay(x,-1); 138 if(lson[x]==-1 && rson[x]==-1) 139 { 140 root=-1; 141 return; 142 } 143 if(lson[x]==-1) 144 { 145 root=rson[x]; 146 par[rson[x]]=-1; 147 return; 148 } 149 if(rson[x]==-1) 150 { 151 root=lson[x]; 152 par[lson[x]]=-1; 153 return; 154 } 155 int pre=lson[root]; 156 while(rson[pre]!=-1) pre=rson[pre]; 157 splay(pre,x); 158 par[pre]=-1; 159 rson[pre]=rson[x]; 160 par[rson[x]]=pre; 161 root=pre; 162 } 163 164 pair<int,int> precursor(int val) 165 { 166 int now=root; 167 int pre=-1; 168 int dif=INF; 169 while(now!=-1) 170 { 171 if(dat[now]<val && val-dat[now]<dif) 172 { 173 pre=now; 174 dif=val-dat[now]; 175 } 176 if(dat[now]>val) now=lson[now]; 177 else now=rson[now]; 178 } 179 return pair<int,int>(dif,pre); 180 } 181 182 pair<int,int> succeed(int val) 183 { 184 int now=root; 185 int suc=-1; 186 int dif=INF; 187 while(now!=-1) 188 { 189 if(dat[now]>val && dat[now]-val<dif) 190 { 191 suc=now; 192 dif=dat[now]-val; 193 } 194 if(dat[now]>val) now=lson[now]; 195 else now=rson[now]; 196 } 197 return pair<int,int>(dif,suc); 198 } 199 200 int main() 201 { 202 cin>>n; 203 for(int i=0;i<n;i++) 204 { 205 cin>>a>>b; 206 if(siz==0) 207 { 208 insert(b); 209 type=a; 210 } 211 else 212 { 213 if(a==type) insert(b); 214 else 215 { 216 pair<int,int> pre=precursor(b); 217 pair<int,int> suc=succeed(b); 218 pair<int,int> res=min(pre,suc); 219 erase(res.second); 220 ans=(ans+res.first)%MOD; 221 } 222 } 223 } 224 cout<<ans<<endl; 225 }