zoukankan      html  css  js  c++  java
  • bzoj 1095: [ZJOI2007]Hide 捉迷藏

    bzoj 1095: [ZJOI2007]Hide 捉迷藏

    Description

    捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的距离。

    Input

    第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,
    表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如
    上文所示。

    Output

    对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关
    着灯的,输出0;若所有房间的灯都开着,输出-1。

    Sample Input

    8

    1 2

    2 3

    3 4

    3 5

    3 6

    6 7

    6 8

    7

    G

    C 1

    G

    C 2

    G

    C 1

    G

    Sample Output

    4

    3

    3

    4

    HINT

    对于(100\%)的数据,(N le 100000, M le 500000)

    上次罗老师讲了这道题,今天才写这道题。

    此题我们首先要进行树分治。

    先通过树分治的重心建一棵树,每个节点维护两个堆,一个维护子树到节点的距离,另一个维护其子树的第一个堆的堆顶。

    我们再利用一个全局堆维护答案。

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
     
    const int N = 100013;
     
    class heap {
    protected:
        priority_queue < int > A, B;
    public:
        void push(const int &x) {
            A.push(x);
        }
        void erase(const int &x) {
            B.push(x);
        }
        void pop() {
            while (!B.empty() && !(A.top() ^ B.top()))
                A.pop(), B.pop();
            A.pop();
        }
        int top() {
            while (!B.empty() && !(A.top() ^ B.top()))
                A.pop(), B.pop();
            return A.empty() ? -0x3f3f3f3f : A.top();
        }
        int size() const {
            return A.size() - B.size();
        }
        bool empty() const {
            return !(A.size() ^ B.size());
        }
        int tps() {
            if (size() < 2) return -0x3f3f3f3f;
            int t1, t2;
            while (!B.empty() && !(A.top() ^ B.top()))
                A.pop(), B.pop();
            t1 = A.top(); A.pop();
            while (!B.empty() && !(A.top() ^ B.top()))
                A.pop(), B.pop();
            t2 = A.top(); A.push(t1);
            return t1 + t2;
        }
    }GlobleHeap, FirstHeap[N], SecondHeap[N];
     
    struct edge {
        int t;
        edge *n;
    } me[N << 1 | 1], *ce = me, *g[N];
     
    inline void adde(const int &a, const int &b) {
        ce->t = b, ce->n = g[a], g[a] = ce++;
    }
     
    int deep[N], fa[20][N], dis[20][N], size[N], f[N], totsize, rt, tot_off;
    bool vis[N], on[N];
     
    inline void cmax(int &a, const int &b) {
        if (a < b) a = b;
    }
     
    void grt(int u, int father) {
        int v;
        size[u] = 1, f[u] = 0;
        for (edge *it = g[u]; it; it = it->n) {
            v = it->t;
            if (vis[v] || (v == father)) continue;
            grt(v, u);
            size[u] += size[v];
            cmax(f[u], size[v]);
        }
        cmax(f[u], totsize - size[u]);
        if (f[u] < f[rt]) rt = u;
    }
     
    void dfs(int u, const int &anc, int father, int dep) {
        int v;
        for (edge *it = g[u]; it; it = it->n) {
            v = it->t;
            if (vis[v] || (v == father)) continue;
            fa[++deep[v]][v] = anc;
            dis[deep[v]][v] = dep;
            dfs(v, anc, u, dep + 1);
        }
    }
     
    void build(int u) {
        int v, all = totsize;
        vis[u] = true;
        dfs(u, u, 0, 1);
        for (edge *it = g[u]; it; it = it->n) {
            if (vis[v = it->t]) continue;
            if (size[u] < size[v])
                size[v] = all - size[u];
            totsize = size[v];
            rt = 0;
            grt(v, u);
            build(rt);
        }
    }
     
    inline void turn_off(const int &u) {
        static int t, i, pre;
        SecondHeap[u].push(0);
        if (SecondHeap[u].size() == 2)
            GlobleHeap.push(SecondHeap[u].top());
        for (i = deep[u]; i > 1; --i)
            if (FirstHeap[fa[i][u]].empty()) {
                FirstHeap[fa[i][u]].push(dis[i - 1][u]);
                pre = SecondHeap[fa[i - 1][u]].tps();
                SecondHeap[fa[i - 1][u]].push(dis[i - 1][u]);
                if (pre > 0) {
                    if (pre ^ (t = SecondHeap[fa[i - 1][u]].tps())) {
                        GlobleHeap.erase(pre);
                        GlobleHeap.push(t);
                    }
                } else if ((t = SecondHeap[fa[i - 1][u]].tps()) > 0)
                           GlobleHeap.push(t);
            } else {
                t = FirstHeap[fa[i][u]].top();
                FirstHeap[fa[i][u]].push(dis[i - 1][u]);
                if (t < dis[i - 1][u]) {
                    pre = SecondHeap[fa[i - 1][u]].tps();
                    SecondHeap[fa[i - 1][u]].erase(t);
                    SecondHeap[fa[i - 1][u]].push(dis[i - 1][u]);
                    if (pre > 0 && (pre ^ (t = SecondHeap[fa[i - 1][u]].tps()))) {
                        GlobleHeap.erase(pre);
                        GlobleHeap.push(t);
                    }
                }
            }
    }
     
    inline void turn_on(const int &u) {
        SecondHeap[u].erase(0);
        if (SecondHeap[u].size() == 1)
            GlobleHeap.erase(SecondHeap[u].top());
        for (int t, pre, i = deep[u]; i > 1; --i) {
            FirstHeap[fa[i][u]].erase(dis[i - 1][u]);
            if (FirstHeap[fa[i][u]].top() < dis[i - 1][u]) {
                pre = SecondHeap[fa[i - 1][u]].tps();
                SecondHeap[fa[i - 1][u]].erase(dis[i - 1][u]);
                if (!FirstHeap[fa[i][u]].empty())
                    SecondHeap[fa[i - 1][u]].push(FirstHeap[fa[i][u]].top());
                if (pre > 0 && (pre ^ (t = SecondHeap[fa[i - 1][u]].tps()))) {
                    GlobleHeap.erase(pre);
                    if (SecondHeap[fa[i - 1][u]].size() > 1)
                        GlobleHeap.push(t);
                }
            }
        }
    }
     
    inline void Switch(const int &u) {
        if (on[u]) turn_off(u);
        else turn_on(u);
        on[u] ^= 1;
        if (on[u]) --tot_off;
        else ++tot_off;
    }
     
    int main() {
        //freopen("1095.in", "r", stdin);
        int n, m, u, v;
        char ops[4];
        scanf("%d", &n);
        for (m = 1; m < n; ++m) {
            scanf("%d%d", &u, &v);
            adde(u, v), adde(v, u);
        }
        f[0] = 0x3f3f3f3f;
        totsize = tot_off = n;
        grt(1, 0);
        build(rt);
        for (m = 1; m <= n; ++m)
            fa[++deep[m]][m] = m, turn_off(m);
        scanf("%d", &m);
        while (m--) {
            scanf("%s", ops);
            if (*ops == 'G') {
                if (!tot_off)puts("-1");
                else printf("%d
    ", max(GlobleHeap.top(), 0));
            } else {
                scanf("%d", &u);
                Switch(u);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    斯特林公式
    高精度算法
    容斥原理
    贪心问题之——Dijkstra最短路
    博弈论
    JavaScript数据类型
    JavaScript变量
    认识JavaScript
    编程语言与计算机
    CSS验证工具
  • 原文地址:https://www.cnblogs.com/cycleke/p/6322597.html
Copyright © 2011-2022 走看看