[luogu2286][寵物收養所]
阿新 • • 發佈:2018-12-01
題目連結
思路
比較裸的一道平衡樹的題。用一個變數S來表示當前樹的情況,當S為負數時樹內為寵物,當S為正數時樹內為人。然後每次分情況討論一下。如果樹為空或者是與來的東西(人或寵物)與樹記憶體的相同。那麼就無法領養,直接將這個東西扔到樹裡。否則就從樹裡面找一個與當前值最接近的數字,然後統計進答案。
一開始把INF設的太小了影響了統計答案。
程式碼
#include<cstdlib> #include<ctime> #include<cstdio> #include<iostream> #define ls TR[cur].ch[0] #define rs TR[cur].ch[1] using namespace std; typedef long long ll; const int N = 100000,mod = 1000000; const ll INF = 1e17 + 10; ll read() { ll x=0,f=1;char c=getchar(); while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } struct node { int ch[2],id; ll val; }TR[N]; void rotate(int &cur,int f) { int son = TR[cur].ch[f]; TR[cur].ch[f] = TR[son].ch[f ^ 1]; TR[son].ch[f ^ 1] = cur; cur = son; } int tot; void insert(int &cur,int val) { if(!cur) { cur = ++tot; TR[cur].val = val; TR[cur].id = rand(); return; } int d = val > TR[cur].val; insert(TR[cur].ch[d],val); if(TR[TR[cur].ch[d]].id < TR[cur].id) rotate(cur,d); } void del(int &cur,int val) { if(!cur) return; if(val == TR[cur].val) { if(!ls || !rs) {cur = ls + rs;return;} int d = TR[ls].id > TR[rs].val; rotate(cur,d); del(cur,val); } del(TR[cur].ch[val > TR[cur].val],val); } ll pred(int cur,int val) { if(!cur) return -INF; if(val <= TR[cur].val) return pred(ls,val); return max(TR[cur].val,pred(rs,val)); } ll nex(int cur,int val) { if(!cur) return INF; if(val >= TR[cur].val) return nex(rs,val); return min(TR[cur].val,nex(ls,val)); } int S; ll ans; int main() { srand(time(0)); int n = read(),rt = 0; while(n--) { int bz = read(),x = read(); if(bz == 0) { if(S <= 0) insert(rt,x); else { int k1 = pred(rt,x),k2 = nex(rt,x); int dele = k1; if(k2 - x < x - k1) dele = k2; ans += abs(dele - x); ans %= mod; del(rt,dele); } S--; } if(bz == 1) { if(S >= 0) insert(rt,x); else { int k1 = pred(rt,x),k2 = nex(rt,x); int dele = k1; if(k2 - x < x - k1) dele = k2; ans += abs(dele - x); ans %= mod; del(rt,dele); } S++; } } cout<<ans<<endl; }