1. 程式人生 > >[luogu2286][寵物收養所]

[luogu2286][寵物收養所]

題目連結

思路

比較裸的一道平衡樹的題。用一個變數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;
}

一言

無論做什麼,記得為自己而做,那就毫無怨言。 ——流金歲月