BZOJ 1208 [HNOI2004]宠物收养所:Splay(伸展树)

时间:2021-09-15 09:45:49

题目链接: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 }