1095: [ZJOI2007]Hide 捉迷藏

1095: [ZJOI2007]Hide 捉迷藏

链接

分析:

  动态点分治。Qtree4没过。。。

  先建出点分树,然后每个点维护两个堆,一个h1表示当前根的连通块内,所有点到点分树上父节点的距离,h2表示当前根的所有子节点的h1的最大值。

  更新的时候,深度是log的,暴力修改堆中的元素即可。

代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<bitset>
#define fore(i, u, v) for (int i = head[u], v = e[i].to; i; i = e[i].nxt, v = e[i].to)
using namespace std;
typedef long long LL;

inline int read() {
    int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 200005;
struct Edge { int to, nxt, w; } e[N << 1];
int head[N], dep[N], f[N][20], Log[N], pos[N], siz[N], fa[N];
bool vis[N], col[N];
int n, En, Mn, Root, Index, Size;

struct Heap{
    priority_queue<int> h, d;
    inline void Insert(int x) { h.push(x); }
    inline void Delete(int x) { d.push(x); }
    inline int Size() { return h.size() - d.size(); }
    inline void Fix() { while (d.size() && h.top() == d.top()) h.pop(), d.pop(); }
    inline int Top() { Fix(); return h.top(); } 
    inline int Sec() { Fix(); int t1 = h.top(), t2; h.pop(); Fix(); t2 = h.top(); h.push(t1); return t2; } // 取次大值之前也要fix一下
    void Change(int x,bool f) { f ? Delete(x) : Insert(x); }
    void pr() {
        
    }
}h1[N], h2[N], Ans;

inline void add_edge(int u,int v,int w) {
    ++En; e[En].nxt = head[u], e[En].to = v, e[En].w = w; head[u] = En; 
    ++En; e[En].nxt = head[v], e[En].to = u, e[En].w = w; head[v] = En; 
}
void predfs(int u,int fa) {
    pos[u] = ++Index; f[Index][0] = dep[u];
    fore(i, u, v) if (v != fa) dep[v] = dep[u] + e[i].w, predfs(v, u), f[++Index][0] = dep[u];
}
void prermq() {
    for (int i = 2; i <= Index; ++i) Log[i] = Log[i >> 1] + 1;
    for (int j = 1; j <= Log[Index]; ++j) 
        for (int i = 1; i + (1 << j) - 1 <= Index; ++i) 
            f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
void getroot(int u,int fa) {
    int mx = 0; siz[u] = 1;
    fore(i, u, v) 
        if (!vis[v] && v != fa) {
            getroot(v, u);
            siz[u] += siz[v]; siz[v] > mx ? mx = siz[v] : mx;
        } 
    mx = max(mx, Size - siz[u]);
    if (mx < Mn) Mn = mx, Root = u;    
}
void dfs(int u,int fa,int d,Heap &A) {
    A.Insert(d); 
    fore(i, u, v) if (!vis[v] && v != fa) dfs(v, u, d + e[i].w, A);
}
void Add(Heap &A) { if (A.Size() >= 2) Ans.Insert(A.Top() + A.Sec()); }
void Del(Heap &A) { if (A.Size() >= 2) Ans.Delete(A.Top() + A.Sec()); }
void solve(int u) {
    vis[u] = 1, h2[u].Insert(0); 
    fore(i, u, v) 
        if (!vis[v]) {
            Heap tmp; dfs(v, u, e[i].w, tmp);
            Mn = 1e9, Size = siz[v], getroot(v, u); 
            fa[Root] = u; h1[Root] = tmp, h2[u].Insert(tmp.Top());
            solve(Root);
        }
    Add(h2[u]);
}
int LCA(int x,int y) {
    if (pos[x] > pos[y]) swap(x, y);
    int k = Log[pos[y] - pos[x] + 1];
    return min(f[pos[x]][k], f[pos[y] - (1 << k) + 1][k]); // !!!
}
int getdis(int x,int y) { return dep[x] + dep[y] - 2 * LCA(x, y); }
void update(int x,bool f) {
    Del(h2[x]), h2[x].Change(0, f), Add(h2[x]);
    for (int now = x; fa[now]; now = fa[now]) {
        Del(h2[fa[now]]);
        if (h1[now].Size()) h2[fa[now]].Delete(h1[now].Top());
        h1[now].Change(getdis(x, fa[now]), f);
        if (h1[now].Size()) h2[fa[now]].Insert(h1[now].Top());
        Add(h2[fa[now]]);
    }
}
char getc() {
    char ch = getchar();
    for (; ch != 'G' && ch != 'C'; ch = getchar());
    return ch;
}
int main() {
    n = read();
    for (int u, v, w, i = 1; i < n; ++i) 
        u = read(), v = read(), add_edge(u, v, 1);
    predfs(1, 0); prermq();
    Mn = 1e9, Size = n, getroot(1, 0); solve(Root);
    int m = read(), White = n, x;
    char opt[5];
    while (m --) {
        if (getc() == 'C') x = read(), update(x, col[x] ^= 1), White += col[x] ? -1 : 1;
        else if (!White) puts("They have disappeared.");
        else printf("%d
", White > 1 ? max(0, Ans.Top()) : 0);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/mjtcn/p/10593982.html