• [NOIP 2016] 天天爱跑步


    [题目链接]

               http://uoj.ac/problem/261

    [算法]

              树上差分 , 时间复杂度 : O(N + M)

    [代码]

           

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 1000010
    
    struct edge
    {
            int to,nxt;
    } e[MAXN << 1];
    
    int n,m,tot,timer;
    bool visited[MAXN];
    int f[MAXN],seq[MAXN],dfn[MAXN],fa[MAXN],dep[MAXN],w[MAXN],s[MAXN],t[MAXN],
            w1[MAXN],w2[MAXN],ans[MAXN],head[MAXN],size[MAXN],lca[MAXN],cnt1[MAXN],cnt2[MAXN];
    vector< pair<int,int> > q[MAXN],tag1[MAXN],tag2[MAXN],pos[MAXN];
    
    template <typename T> inline void read(T &x)
    {
        int 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 int get_root(int x)
    {
            if (f[x] == x) return x;
            return f[x] = get_root(f[x]);
    }
    inline void tarjan(int u,int father)
    {
            dfn[u] = ++timer;
            seq[timer] = u;
            size[u] = 1;
            visited[u] = true;
            for (int i = 0; i < (int)q[u].size(); i++)
            {
                    int v = q[u][i].first , id = q[u][i].second;
                    if (visited[v]) lca[id] = get_root(v); 
            }
            for (int i = head[u]; i; i = e[i].nxt)
            {
                    int v = e[i].to;
                    if (v == father) continue;
                    dep[v] = dep[u] + 1;
                    tarjan(v,u);
                    fa[v] = f[v] = u;
                    size[u] += size[v];
            }
    }
    int main() 
    {
            
            read(n); read(m);
            for (int i = 1; i < n; i++)
            {
                    int u,v;
                    read(u); read(v);
                    addedge(u,v);
                    addedge(v,u);
            }
            for (int i = 1; i <= n; i++) read(w[i]);
            for (int i = 1; i <= n; i++) f[i] = i;
            for (int i = 1; i <= m; i++)
            {
                    read(s[i]);
                    read(t[i]);    
                    q[s[i]].push_back(make_pair(t[i],i));
                    q[t[i]].push_back(make_pair(s[i],i));
            } 
            tarjan(1,-1);
            for (int i = 1; i <= n; i++) w1[i] = dep[i] + w[i];
            for (int i = 1; i <= n; i++) w2[i] = dep[i] - w[i];
            for (int i = 1; i <= m; i++)
            {
                    if (lca[i] == s[i]) 
                    {
                            tag2[t[i]].push_back(make_pair(dep[s[i]],1));
                            tag2[fa[s[i]]].push_back(make_pair(dep[s[i]],-1));
                    } else if (lca[i] == t[i])
                    {
                            tag1[s[i]].push_back(make_pair(dep[s[i]],1));
                            tag1[fa[t[i]]].push_back(make_pair(dep[s[i]],-1));
                    } else
                    {
                            tag1[s[i]].push_back(make_pair(dep[s[i]],1));
                            tag1[fa[lca[i]]].push_back(make_pair(dep[s[i]],-1));
                            tag2[t[i]].push_back(make_pair(2 * dep[lca[i]] - dep[s[i]],1));
                            tag2[lca[i]].push_back(make_pair(2 * dep[lca[i]] - dep[s[i]],-1));
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    pos[dfn[i] - 1].push_back(make_pair(i,-1));
                    pos[dfn[i] + size[i] - 1].push_back(make_pair(i,1));
            }
            int val = 2 * n;
            for (int i = 1; i <= n; i++)
            {
                    int u = seq[i];
                    for (int j = 0; j < (int)tag1[u].size(); j++)
                            cnt1[tag1[u][j].first + val] += tag1[u][j].second;
                    for (int j = 0; j < (int)tag2[u].size(); j++)
                            cnt2[tag2[u][j].first + val] += tag2[u][j].second; 
                    for (int j = 0; j < (int)pos[i].size(); j++)
                    {
                            ans[pos[i][j].first] += cnt1[w1[pos[i][j].first] + val] * pos[i][j].second;
                            ans[pos[i][j].first] += cnt2[w2[pos[i][j].first] + val] * pos[i][j].second; 
                    }
            }
            for (int i = 1; i < n; i++) printf("%d ",ans[i]);
            printf("%d
    ",ans[n]);
            
            return 0;
        
    }
  • 相关阅读:
    好记性不如烂笔头-linux学习笔记2kickstart自动化安装和cacti
    好记性不如烂笔头-linux学习笔记1
    关于TP5中的依赖注入和容器和facade
    vbs 脚本2
    vbs脚本
    Memcache 和 Radis 比较
    MongoDB 索引的使用, 管理 和优化
    mysql大数据高并发处理
    sql处理高并发
    LB 负载均衡的层次结构
  • 原文地址:https://www.cnblogs.com/evenbao/p/9529620.html
Copyright © 2020-2023  润新知