8.Bzoj1208: [HNOI2004]寵物收養所 (Treap)
阿新 • • 發佈:2018-11-29
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; }
考察點
對題意的理解 與 程式碼封裝的考驗