zoukankan      html  css  js  c++  java
  • 洛谷P3258 [JLOI2014]松鼠的新家

    题目描述

    松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。

    松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。

    维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。

    因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

    输入输出格式

    输入格式:

    第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an

    接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

    输出格式:

    一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。

    输入输出样例

    输入样例#1: 复制
    5
    1 4 5 3 2
    1 2
    2 4
    2 3
    4 5
    输出样例#1: 复制
    1
    2
    1
    2
    1

    说明

    2<= n <=300000

    (这张图片转的23333)

    /*
        真不知道这么简单的题目怎么紫的23333
        还是树上差分的点差分 和最大流那题基本一样
        要注意的是因为求解时每个除了第一个和最后一个a[i]会多用一次
        所以最后的结果这些a[i]要-- 然后a[n]那里没饭吃 也要--
        其他真的和最大流没有区别了TAT
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int MAXN = 300010;
    
    int deep[MAXN],f[MAXN][25],lg[MAXN],head[MAXN],cnt;
    int n,m,s,ppt[MAXN],a[MAXN];
    
    struct node{
        int to,pre;
    }G[MAXN<<2];
    
    void add(int from,int to){
        G[++cnt].to = to;
        G[cnt].pre = head[from];
        head[from] = cnt;
    }
    
    inline int read() {
         int x = 0,m = 1;
         char ch;
         while(ch < '0' || ch > '9')  {if(ch == '-') m = -1;ch = getchar();}
         while(ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch=getchar();}
         return m * x;
     }
    
    inline void dfs1(int u)
    {
        for(int i = head[u];i;i = G[i].pre)
        {
            int v = G[i].to;
            if(v != f[u][0])
            {
                f[v][0] = u;
                deep[v] = deep[u] + 1;
                dfs1(v);
            }
        }
    }
    
    inline int lca(int u,int v)
    {
        if(deep[u] < deep[v]) swap(u,v);
        int dis = deep[u] - deep[v];
        for(register int i = 0;i <= lg[n];i++)
        {
            if((1 << i) & dis) u = f[u][i];
        }
        if(u == v) return u;
        for(register int i = lg[deep[u]];i >= 0;i--)
        {
            if(f[u][i] != f[v][i])
            {
                u = f[u][i];v = f[v][i];
            }
        }
        return f[u][0];
    }
    
    inline void init()
    {
        for(register int i = 1;i <= n;i++)
        {
            lg[i] = lg[i-1] + (1 << lg[i-1] + 1 == i);
        }
        for(register int j = 1;j <= lg[n];j++)
        {
            for(register int i = 1;i <= n;i++)
            {
                if(f[i][j-1] != -1)
                f[i][j] = f[f[i][j-1]][j-1];
            }
        }
    }
    
    inline void dfs2(int u,int fa){
        for(int i = head[u];i;i = G[i].pre){
            int v = G[i].to;
            if(v == fa) continue;
            dfs2(v,u);
            ppt[u] += ppt[v];
        }
    }
    
    int main()
    {
        int x,y;
        n = read();
        for(register int i = 1;i <= n;i++){
            a[i] = read();
        }
        for(register int i = 1;i <= n-1;i++)
        {
            x = read();y = read();
            add(x,y);add(y,x);
        }
        dfs1(1);
        init();
        for(int i = 1;i <= n-1;i++){
            x = a[i];y = a[i+1];//可以看到这里多算了一次
            int Lca = lca(x,y);
            ppt[x]++,ppt[y]++,ppt[Lca]--,ppt[f[Lca][0]]--;//还是树上差分的操作
        }
        dfs2(1,0);
        for(int i = 2;i <= n;i++) ppt[a[i]]--;//一定要注意这里--
        for(int i = 1;i <= n;i++){
            printf("%d
    ",ppt[i]);
        }
        return 0;
    }
  • 相关阅读:
    oracle 数据库服务名怎么查
    vmware vsphere 6.5
    vSphere虚拟化之ESXi的安装及部署
    ArcMap中无法添加ArcGIS Online底图的诊断方法
    ArcGIS中字段计算器(高级计算VBScript、Python)
    Bad habits : Putting NOLOCK everywhere
    Understanding the Impact of NOLOCK and WITH NOLOCK Table Hints in SQL Server
    with(nolock) or (nolock)
    What is “with (nolock)” in SQL Server?
    Changing SQL Server Collation After Installation
  • 原文地址:https://www.cnblogs.com/bryce02/p/9897259.html
Copyright © 2011-2022 走看看