zoukankan      html  css  js  c++  java
  • 「题解」洛谷 P2286 [HNOI2004]宠物收养场

    题目

    P2286 [HNOI2004]宠物收养场

    简化题意

    有一堆人和一堆宠物,来的有先后顺序,每个人想要一只 特点值为 (a) 的宠物,我们会从现有的猫中调一只和这个 (a) 差的最小的,如果有差相同的就选特点值小的。

    如果人多出了,来了一只猫找的也是差最小的人。

    计算每次配对的宠物的特点值和人想要的特点值得差的绝对值的和。

    思路

    Splay。

    简单的维护前驱后继的问题。Splay维护一下。

    至此,今天的第一课 Splay 终于写完了,早自习码完代码,找 bug 找了一上午。。。

    Code

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #define MAXN 100001
    
    inline void read(int &T) {
        int x = 0;
        bool f = 0;
        char c = getchar();
        while (c < '0' || c > '9') {
            if (c == '-') f = !f;
            c = getchar();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = getchar();
        }
        T = f ? -x : x;
    }
    
    const int mod = 1000000;
    int n, root, ans, fa[MAXN], son[MAXN][2];
    int num, size[MAXN], cnt[MAXN], val[MAXN];
    
    int which(int x) { return son[fa[x]][1] == x ? 1 : 0; }
    
    void update(int x) { size[x] = cnt[x] + size[son[x][0]] + size[son[x][1]]; }
    
    void clear(int x)  { fa[x] = son[x][0] = son[x][1] = cnt[x] = size[x] = val[x] = 0; }
    
    void rotate(int x) {
        int father = fa[x], grandpa = fa[father];
        int flag1 = which(x), flag2 = which(father);
        fa[x] = grandpa, fa[father] = x;
        if (grandpa) son[grandpa][flag2] = x;
        fa[son[x][flag1 ^ 1]] = father;
        son[father][flag1] = son[x][flag1 ^ 1];
        son[x][flag1 ^ 1] = father;
        update(x), update(father);
    }
    
    void splay(int x) {
        for (int f = fa[x]; f = fa[x], f; rotate(x)) {
            if (fa[f]) rotate(which(x) == which(f) ? f : x);
        }
        root = x;
    }
    
    int pre() {
        int now = son[root][0];
        while (son[now][1]) now = son[now][1];
        splay(now); return now;
    }
    
    int nxt() {
        int now = son[root][1];
        while (son[now][0]) now = son[now][0];
        splay(now); return now;
    }
    
    int qrank(int x) {
        int ans = 0, now = root;
        while (1) {
            if (val[now] > x) now = son[now][0];
            else {
                ans += size[son[now][0]];
                if (val[now] == x) {
                    splay(now);
                    return ans + 1;
                }
                ans += cnt[now];
                now = son[now][1];
            }
        }
    }
    
    void ins(int x) {
        if (!root) {
            val[++num] = x;
            ++cnt[num];
            root = num;
            update(num);
            return;
        }
        int now = root, f = 0;
        while (1) {
            if (val[now] == x) {
                ++cnt[now];
                update(now), update(f);
                splay(now);
                return;
            }
            f = now, now = son[now][val[now] < x];
            if (!now) {
                val[++num] = x, ++cnt[num];
                fa[num] = f, son[f][val[f] < x] = num;
                update(num), update(f), splay(num);
                return;
            }
        }
    }
    
    void del(int x) {
        qrank(x);
        if (cnt[root] > 1) {
            --cnt[root];
            update(root);
            return;
        }
        if (!son[root][0] && !son[root][1]) {
            clear(root);
            root = 0;
            return;
        }
        if (!son[root][0]) {
            int now = root;
            root = son[root][1];
            fa[root] = 0;
            clear(now);
            return;
        }
        if (!son[root][1]) {
            int now = root;
            root = son[root][0];
            fa[root] = 0;
            clear(now);
            return;
        }
        int now = root, k = pre();
        son[k][1] = son[now][1];
        fa[son[now][1]] = k;
        clear(now), update(root);
    }
    
    int main() {
        read(n);
        int typ_, tot = 0;
        for (int i = 1, typ, x; i <= n; ++i) {
            read(typ), read(x);
            if (!tot) {
                typ_ = typ;
                ins(x);
                ++tot;
            }
            else {
                if (typ_ == typ) ++tot, ins(x);
                else {
                    --tot;
                    ins(x);
                    if (cnt[root] > 1) del(x);
                    else {
                        int minn = 2147483647, maxx = 2147483647;
                        int rt = root;
                        if (son[root][0]) minn = val[pre()];
                        splay(rt);
                        if (son[root][1]) maxx = val[nxt()];
                        splay(rt);
                        if (son[root][0] && son[root][1]) {
                            if (abs(x - minn) <= abs(maxx - x)) {
                                ans = (1ll * ans + 1ll * x - 1ll * minn) % mod;
                                del(minn);
                            }
                            else {
                                ans = (1ll * ans + 1ll * maxx - 1ll * x) % mod;
                                del(maxx);
                            }
                        }
                        else {
                            if (son[root][0]) {
                                ans = (1ll * ans + 1ll * x - 1ll * minn) % mod;
                                del(minn);
                            }
                            else if (son[root][1]) {
                                ans = (1ll * ans + 1ll * maxx - 1ll * x) % mod;
                                del(maxx);
                            }
                        }
                    }
                    del(x);
                }
            }
        }
        std::cout << ans << '
    ';
        return 0;
    }
    
  • 相关阅读:
    初步学习pg_control文件之四
    初步学习pg_control文件之三
    初步学习pg_control文件之二
    初步认识pg_control文件之一
    Slony-I的 RemoteWorker重试调查
    对Slony-I中wait on的理解
    超高逼格Log日志打印
    实现列表二级展开/收起/选择
    贝塞尔曲线实现购物车飞入效果
    乐鑫esp8266的 基于Nonos移植红外线1883,实现遥控器控制
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/13638778.html
Copyright © 2011-2022 走看看