Bzoj1208: [HNOI2004]宠物收养所 (Treap)
这个题要求求前驱和后继,然后对宠物造一颗树,对人造一颗树.
代码不难写,题意比较难懂.
当新来一只宠物时,如果此时没有人,人树为空时.那么这只宠物就暂时存下来,如果有人,那么久领养.
同理,人也是这样.
#include <iostream>
#include <cstdio>
#include <algorithm>
#define rep(i , x, p) for(int i = x;i <= p;++ i)
#define sep(i , x, p) for(int i = x;i >= p;-- i)
#define gc getchar()
#define pc putchar
using namespace std;
const int inf = 1e9;
const int maxN = 100000 + 7;
const int mod = 1000000;
inline int read() {int x = 0,f = 1;char c = gc;while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;}
void print(int x) {if(x < 0) pc('-') , x = -x;if(x >= 10) print(x / 10);pc(x % 10 + '0');}
struct Node {
int ch[maxN][2] , pos[maxN], size[maxN], key[maxN], rt, cnt;
void up(int i) {size[i] = size[ch[i][0]] + size[ch[i][1]] + 1;return ;}
void spin(int &i , int p) {
int tmp = ch[i][p];
ch[i][p] = ch[tmp][!p];ch[tmp][!p] = i;up(i);i = tmp;up(i);
}
void Insert(int &i , int x) {
if(!i) {
++ cnt;i = cnt;
size[i] = 1;pos[i] = rand();
key[i] = x;
return ;
}
if(key[i] >= x) {
Insert(ch[i][0] , x);
if(pos[i] < pos[ch[i][0]]) spin(i , 0);
}
else {
Insert(ch[i][1] , x);
if(pos[i] < pos[ch[i][1]]) spin(i , 1);
}
up(i);
}
int pre(int i , int x) {
if(!i) return -inf;
if(key[i] < x) return max(pre(ch[i][1] , x) , key[i]);
return pre(ch[i][0] , x);
}
int nxt(int i , int x) {
if(!i) return inf;
if(key[i] > x) return min(nxt(ch[i][0] , x) , key[i]);
return nxt(ch[i][1] , x);
}
void Dele(int &i , int x) {
if(key[i] == x) {
if(ch[i][0] * ch[i][1] == 0) {i = ch[i][0] + ch[i][1];return ;}
if(pos[ch[i][0]] > pos[ch[i][1]]) {spin(i , 1); Dele(ch[i][0] , x);}
else {spin(i , 0) , Dele(ch[i][1] , x);}
}else {
if(x < key[i]) Dele(ch[i][0] , x);
else Dele(ch[i][1] , x);
}
up(i);
}
}f1 , f2;
int ans;
void work1(int x) {
int q1 = f1.pre(f1.rt , x) , q2 = f1.nxt(f1.rt , x) , tmp;
if(q1 == -inf) {tmp = q2 - x , f1.Dele(f1.rt , q2);}
else if(q2 == inf) {tmp = x - q1 , f1.Dele(f1.rt , q1);}
else if(abs(q1 - x) <= abs(q2 - x) ) {f1.Dele(f1.rt , q1);tmp = x - q1;}
else {f1.Dele(f1.rt , q2);tmp = q2 - x;}
ans = (ans + tmp) % mod ;
}
void work2(int x) {
int q1 = f2.pre(f2.rt , x) , q2 = f2.nxt(f2.rt , x) , tmp;
if(q1 == -inf) {tmp = q2 - x , f2.Dele(f2.rt , q2);}
else if(q2 == inf) {tmp = x - q1 , f2.Dele(f2.rt , q1);}
else if(x - q1 <= q2 - x) {f2.Dele(f2.rt , q1);tmp = x - q1;}
else {f2.Dele(f2.rt , q2);tmp = q2 - x;}
ans = (ans + tmp) % mod ;
}
int main() {
int n = read() , opt, x, l1 = 0, l2 = 0;
rep(i , 1, n) {
opt = read();x = read();
if(opt == 0) {l1 ++;if(l2) work2(x), l1 -- ,l2 --;else f1.Insert(f1.rt , x);}
else {l2 ++;if(l1) work1(x) , l1 -- ,l2 --;else f2.Insert(f2.rt , x);}
}
print(ans);
return 0;
}
考察点
对题意的理解 与 代码封装的考验