zoukankan      html  css  js  c++  java
  • [ZJOI 2007] 捉迷藏

    [题目链接]

           https://www.lydsy.com/JudgeOnline/problem.php?id=1095

    [算法]

            首先建出点分树,然后每一个点开两个堆。“第一个堆记录子树中所有节点到父亲节点的距离 ,第二个堆记录所有子节点的堆顶 ,那么一个节点的堆2中的最大和次大加起来就是子树中经过这个节点的最长链。然后我们最后开一个全局的堆,记录所有堆2中最大值和次大值之和。那么全局的堆顶就是答   

            案

            时间复杂度 : O(NlogN ^ 2)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100010
    #define M 500010
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    int n , root , tot , timer;
    int size[N] , head[N] , weight[N] , father[N] , ans[N];
    bool visited[N] , light[N];
    map< int , pair<int , int> > mp[N];
    
    struct edge
    {
            int to , nxt;
    } e[M << 1];
    
    struct Heap
    {
            priority_queue< int > hp , era;
            inline void ins(int value)
            {
                    hp.push(value);
            }
            inline void del(int value)
            {
                    if (value != 0) era.push(value);
            }
            inline int max()
            {
                    while (!hp.empty() && !era.empty() && era.top() == hp.top())
                    {
                            hp.pop();
                            era.pop();
                    }
                    if (hp.empty()) return 0;
                    else return hp.top();
            }
            inline int secmax()
            {
                    int tmp = max();
                    del(tmp);
                    int ret = max();
                    ins(tmp);
                    return ret;
            }
    } A , B[N] , C[N << 1];
    
    template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
    template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f;
    }
    inline void addedge(int u , int v)
    {
            ++tot;
            e[tot] = (edge){v , head[u]};
            head[u] = tot;
    }
    inline void getroot(int u , int father , int total)
    {
            size[u] = 1;
            weight[u] = 0;
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (v == father || visited[v]) continue;
                    getroot(v , u , total);
                    size[u] += size[v];
                    chkmax(weight[u] , size[v]);
            }
            chkmax(weight[u] , total - size[u]);
            if (weight[u] < weight[root]) root = u;        
    }
    inline void dfs(int u , int father , int rt , int belong , int depth)
    {
            mp[rt][u] = make_pair(belong , depth);
            C[belong].ins(depth);
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (v == father || visited[v]) continue;
                    dfs(v , u , rt , belong , depth + 1);
            }
    }
    inline void work(int u)
    {
            visited[u] = true;
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (!visited[v]) 
                    {
                            dfs(v , u , u , ++timer , 1);
                            B[u].ins(C[timer].max());
                    }
            }        
            ans[u] = B[u].max() + B[u].secmax();
            A.ins(ans[u]);
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (!visited[v])
                    {
                            root = 0;
                            getroot(v , u , size[v]);
                            father[root] = u;
                            work(root);
                    }
            }
    }
    
    int main()
    {
            
            read(n);
            for (int i = 1; i < n; i++)
            {
                    int x , y;
                    read(x); read(y);
                    addedge(x , y);
                    addedge(y , x);
            }
            int q;
            read(q);
            root = 0;
            weight[0] = n;
            getroot(1 , 0 , n);
            work(root);
            int cnt = n;
            while (q--)
            {
                    char type[5];
                    scanf("%s" , type);
                    if (type[0] == 'C')
                    {
                            int x , y;
                            scanf("%d" , &x);
                            y = x;
                            if (light[x])
                            {
                                    light[x] = false;
                                    ++cnt;
                                    A.del(ans[x]);
                                    ans[x] = B[x].max() + B[x].secmax();
                                    A.ins(ans[x]);
                                    x = father[x];
                                    while (x != 0)
                                    {
                                            pair<int , int> tmp = mp[x][y];
                                            B[x].del(C[tmp.first].max());
                                            C[tmp.first].ins(tmp.second);
                                            B[x].ins(C[tmp.first].max());
                                            A.del(ans[x]);
                                            if (light[x])
                                            {
                                                    if (B[x].secmax()) ans[x] = B[x].max() + B[x].secmax();
                                                    else ans[x] = 0;
                                            } else ans[x] = B[x].max() + B[x].secmax();
                                            A.ins(ans[x]);
                                            x = father[x];
                                    }
                            } else
                            {
                                    light[x] = true;
                                    --cnt;
                                    A.del(ans[x]);
                                    if (B[x].secmax()) ans[x] = B[x].max() + B[x].secmax();
                                    else ans[x] = 0;
                                    A.ins(ans[x]);
                                    x = father[x];
                                    while (x != 0)
                                    {
                                            pair<int , int> tmp = mp[x][y];
                                            B[x].del(C[tmp.first].max());
                                            C[tmp.first].del(tmp.second);
                                            B[x].ins(C[tmp.first].max());
                                            A.del(ans[x]);
                                            if (light[x])
                                            {
                                                    if (B[x].secmax()) ans[x] = B[x].max() + B[x].secmax();
                                                    else ans[x] = 0;
                                            } else ans[x] = B[x].max() + B[x].secmax();
                                            A.ins(ans[x]);
                                            x = father[x];
                                    }
                            }
                     } else
                     {
                             if (!cnt) printf("-1
    ");
                            else if (cnt == 1) printf("0
    ");
                            else printf("%d
    " , A.max());        
                    }
            }
            return 0;
        
    }
  • 相关阅读:
    微信小程序------代码构成
    微信小程序------开发测试
    H5中 input消除默认,取消在手机上的点击高亮效果
    html5 WebSocket
    js和jquery如何获取图片真实的宽度和高度_javascript技巧
    如何解决Provisional headers are shown问题(转)
    JQuery怎样返回前一页
    tp5 通过IP获取对应ip的城市
    php 将富文本编辑后的内容转义为不带HTML标签的字符
    tp5 分页样式
  • 原文地址:https://www.cnblogs.com/evenbao/p/10540119.html
Copyright © 2011-2022 走看看