• [Luogu 3258] JLOI2014 松鼠的新家


    [Luogu 3258] JLOI2014 松鼠的新家

    <题目链接>


    LCA + 树上差分。

    我呢,因为是树剖求的 LCA,预处理了 DFN(DFS 序),于是简化成了序列差分。

    qwq不讲了不讲了,贴代码。

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    
    #define nullptr NULL
    
    const int MAXN = 300010; 
    
    int n, a[MAXN]; 
    
    namespace HLD
    {
        int qwq[MAXN]; 
        class Graph
        {
            private: 
                bool vis[MAXN]; 
                int num; 
                struct Node
                {
                    int depth, size, father, son, top, DFN; 
                }s[MAXN]; 
                struct Edge
                {
                    int to; 
                    Edge *next; 
                    Edge(int to, Edge* next): to(to), next(next){}
                    ~Edge(void)
                    {
                        if(next!=nullptr)
                            delete next; 
                    }
                }*head[MAXN]; 
                void Modify(int l, int r, int k)
                {
                    qwq[s[l].DFN] += k; 
                    qwq[s[r].DFN + 1] -= k; 
                }
                void Add(int x, int y)
                {
                    int a, b; 
                    while((a = s[x].top) ^ (b = s[y].top))
                        if(s[a].depth > s[b].depth)
                        {
                            Modify(a, x, 1); 
                            x = s[a].father; 
                        }
                        else
                        {
                            Modify(b, y, 1); 
                            y = s[b].father; 
                        }
                    if(s[x].depth < s[y].depth)
                        Modify(x, y, 1); 
                    else
                        Modify(y, x, 1); 
                }
            public: 
                Graph(int n): num(0)
                {
                    memset(vis, 0, sizeof vis); 
                    memset(s, 0, sizeof s); 
                    std :: fill(head + 1, head + n + 1, (Edge*)nullptr); 
                }
                ~Graph(void)
                {
                    for(int i = 1; i <= n; ++i)
                        delete head[i]; 
                }
                void AddEdges(int u, int v)
                {
                    head[u] = new Edge(v, head[u]); 
                    head[v] = new Edge(u, head[v]); 
                }
                void DFS1(int u, int k)
                {
                    s[u].depth = k; 
                    s[u].size = 1; 
                    int v; 
                    for(Edge* i = head[u]; i != nullptr; i = i -> next)
                        if(!s[v = i -> to].depth)
                        {
                            DFS1(v, k + 1); 
                            s[v].father = u; 
                            s[u].size += s[v].size; 
                            if(s[v].size > s[s[u].son].size)
                                s[u].son = v; 
                        }
                }
                void DFS2(int u, int top)
                {
                    s[u].top = top; 
                    s[u].DFN = ++num; 
                    vis[u] = true; 
                    if(s[u].son)
                        DFS2(s[u].son, top); 
                    int v; 
                    for(Edge* i = head[u]; i != nullptr; i = i -> next)
                        if(!vis[v = i -> to])
                            DFS2(v, v); 
                }
                void Walk(int x, int y)
                {
                    Add(x, y); 
                    Modify(y, y, -1); 
                }
                void Find(void)
                {
                    for(int i = 1; i < n; ++i)
                        qwq[i + 1] += qwq[i]; 
                    for(int i = 1; i <= n; ++i)
                        printf("%d
    ", qwq[s[i].DFN]); 
                }
        }*G; 
        void Init(void)
        {
            G = new Graph(n); 
            for(int i = 1, u, v; i < n; ++i)
            {
                scanf("%d %d", &u, &v); 
                G -> AddEdges(u, v); 
            }
            G -> DFS1(1, 1); 
            G -> DFS2(1, 1); 
        }
    }
    
    int main(void)
    {
        scanf("%d", &n); 
        for(int i = 1; i <= n; ++i)
            scanf("%d", &a[i]); 
        HLD :: Init(); 
        for(int i = 1; i < n; ++i)
            HLD :: G -> Walk(a[i], a[i + 1]); 
        HLD :: G -> Find(); 
        return 0; 
    }
    

    谢谢阅读。

  • 相关阅读:
    nodejs处理get请求
    ubuntu中chromium无法播放flash,安装flash
    JQuery日历控件
    深度理解Jquery 中 offset() 方法
    javascrip中parentNode和offsetParent之间的区别
    JQuery判断元素是否存在
    javascript日历控件——纯javascript版
    canvas作为背景
    background-position控制背景位置
    javascript日历控件
  • 原文地址:https://www.cnblogs.com/Capella/p/9884917.html
Copyright © 2020-2023  润新知