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\n", max(GlobleHeap.top(), 0));
        } else {
            scanf("%d", &u);
            Switch(u);
        }
    }
    return 0;
}
posted @ 2017-01-20 14:10  cycleke  阅读(215)  评论(0编辑  收藏  举报