zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Linux 网络子系统之网络协议接口层(一)
    Linux 网络子系统之结构介绍
    buildroot 制作的文件系统烧入到nand中打开设备没有权限
    kernel 生成uImage
    mount -t nfs 不能使用
    u-boot 2016.05 添加u-boot cmd
    DELPHI中 screen.Cursor:=crhourglass; adoQuery.close; adoquery.Open; screen.Cursor:=crdefault;啥意思
    Oracle客户端下载地址
    Delphi编程建议遵守的规范1---缩进、各种语句的用法
    Delphi数据库技术中Disablecontrols和Enablecontrols的功能
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10593982.html
Copyright © 2011-2022 走看看