• [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;
        
    }
  • 相关阅读:
    【乱侃】How do they look them ?
    【softeware】Messy code,some bug of Youdao notebook in EN win7
    【随谈】designing the login page of our project
    【web】Ad in security code, making good use of resource
    SQL数据库内存设置篇
    关系数据库的查询优化策略
    利用SQL未公开的存储过程实现分页
    sql语句总结
    sql中使用cmd命令注销登录用户
    SQLServer 分页存储过程
  • 原文地址:https://www.cnblogs.com/evenbao/p/10540119.html
Copyright © 2020-2023  润新知