1. 程式人生 > 其它 >BZOJ#1208[HNOI2004]寵物收養場

BZOJ#1208[HNOI2004]寵物收養場

[HNOI2004]寵物收養場

思路:

使用兩個multiset維護找到離當前的主人/寵物的最近的位置,刪掉,亦可以使用平衡樹

程式碼:

#include <bits/stdc++.h>
#define int long long
int _ = 0, Case = 1;
using namespace std;
#define all(v) begin(v),end(v)
#define nline '\n'


void solve(int Case) {
    multiset<int> a, b;
    int n;
    cin >> n;
    int res = 0;
    for (int i = 1; i <= n; i++) {
        int x, y;
        cin >> x >> y;
        if (x) {
            b.insert(y);
        } else {
            a.insert(y);
        }
        while (a.size() >= b.size() and b.size()) {
            auto it = b.begin();
            auto t = a.lower_bound(*it);
            int d1 = 1e9, d2 = 1e9;
            if (t != a.end()) {
                d1 = abs(*t - *it);
            }
            auto t1 = a.lower_bound(*it);
            if (t1 != a.begin()) {
                t1--;
                d2 = abs(*t1 - *it);
            }
            if (d1 < d2) {
                b.erase(it);
                a.erase(t);
                res += d1;
            } else {
                b.erase(it);
                a.erase(t1);
                res += d2;
            }
        }
        while (b.size() >= a.size() and a.size()) {
            auto it = a.begin();
            auto t = b.lower_bound(*it);
            int d1 = 1e9, d2 = 1e9;
            if (t != b.end()) {
                d1 = abs(*t - *it);
            }
            auto t1 = b.lower_bound(*it);
            if (t1 != b.begin()) {
                t1--;
                d2 = abs(*t1 - *it);
            }
            if (d1 < d2) {
                a.erase(it);
                b.erase(t);
                res += d1;
            } else {
                a.erase(it);
                b.erase(t1);
                res += d2;
            }
        }
        res %= 1000000;
        //cout<<res<<nline;
    }
    cout << res << nline;
}
signed main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);
//   cin >> _; for (Case = 1; Case <= _; Case++)
    solve(Case);

    return 0;
}