NOIP2016 天天爱跑步 题解

题目链接

首先,把每条路径拆成如下两条路径。

  1. 从起点到LCA的路径。
  2. 从LCA到终点的路径。

对这两条路径分别处理。

首先,处理从起点到LCA的路径。

为了方便,我们把这条路径拆成两条,进行差分:

用从起点到根的路径,减去从LCA到根的路径,得出这条路径的贡献。

现在我们要处理如下路径:

从x点出发,走到根,出发时间为t,贡献为g(1或-1)。

这个操作对点u有贡献,当且仅当满足如下条件:(设sd[x]为x的深度,w[u]表示结点u出现观察员的时间)

  1. x在u的子树中。
  2. t[x]+(sd[x]-sd[u])=w[u] (即sd[u]+w[u]=sd[x]+t[x])。

所以,开一个数组记录sd[u]+w[u]的出现次数,dfs到u时,用dfs(u)之后的结果-之前的结果,就是u的子树中的x的贡献。(dfs之后比dfs之前仅多包含了u的子树)。

然后,处理从LCA到终点的路径。

同样,拆成两条,进行差分。

我们设从终点为x,起点为根,出发时间为t,贡献为g(1或-1)。

这个操作对点u有贡献,当且仅当满足如下条件:(设sd[x]为x的深度,w[u]表示结点u出现观察员的时间)

  1. x在u的子树中。
  2. w[u]=sd[u]+t[x] (即w[u]-sd[u]=t[x])。

同样,开一个数组记录w[u]-sd[u]的出现次数,然后用同样的方法dfs处理。(这里下标有负数,可以通过同时加一个值来解决)。

代码:

#include <stdio.h>
#include <string.h>
int fr[300010],ne[600010];
int v[600010],bs=0,mi=0;
int shu[300010],son[300010];
int sd[300010],top[300010];
int fa[300010],W[300010];
int sl1[1500010],sl2[1500010];
int sl3[1500010],sl4[1500010];
int jg[300010],lc[300010];
struct SLb
{
    int he[300010];
    int r[1200010];
    int z[1200010];
    int s;
    SLb(){s=0;}
    void addlb(int a,int b)
    {
        z[s]=b;
        r[s]=he[a];
        he[a]=s;
        s+=1;
        if(b<mi)
            mi=b;
    }
};
SLb lb1,lb2,lb3,lb4;
void addb(int a,int b)
{
    v[bs]=b;
    ne[bs]=fr[a];
    fr[a]=bs;
    bs+=1;
}
void dfs1(int u,int f)
{
    fa[u]=f;
    son[u]=-1;
    shu[u]=1;
    if(f==-1)
        sd[u]=0;
    else
        sd[u]=sd[f]+1;
    int ma=0;
    for(int i=fr[u];i!=-1;i=ne[i])
    {
        int t=v[i];
        if(t!=f)
        {
            dfs1(t,u);
            if(shu[t]>ma)
            {
                ma=shu[t];
                son[u]=t;
            }
            shu[u]+=shu[t];
        }
    }
}
void dfs2(int u,int f,int tp)
{
    top[u]=tp;
    if(son[u]==-1)
        return;
    dfs2(son[u],u,tp);
    for(int i=fr[u];i!=-1;i=ne[i])
    {
        if(v[i]!=f&&v[i]!=son[u])
            dfs2(v[i],u,v[i]);
    }
}
int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(sd[top[x]]>sd[top[y]])
            x=fa[top[x]];
        else
            y=fa[top[y]];
    }
    return sd[x]<sd[y]?x:y;
}
void dfs3(int u,int f)
{
    int yq=W[u]-sd[u]+mi;
    int j=(yq<0?0:sl1[yq]);
    for(int i=lb1.he[u];i!=-1;i=lb1.r[i])
        sl1[lb1.z[i]+mi]+=1;
    for(int i=fr[u];i!=-1;i=ne[i])
    {
        if(v[i]!=f)
            dfs3(v[i],u);
    }
    j=(yq<0?0:sl1[yq])-j;
    jg[u]+=j;
}
void dfs4(int u,int f)
{
    int yq=W[u]+sd[u]+mi;
    int j=(yq<0?0:sl2[yq]);
    for(int i=lb2.he[u];i!=-1;i=lb2.r[i])
        sl2[lb2.z[i]+sd[u]+mi]+=1;
    for(int i=fr[u];i!=-1;i=ne[i])
    {
        if(v[i]!=f)
            dfs4(v[i],u);
    }
    j=(yq<0?0:sl2[yq])-j;
    jg[u]+=j;
}
void dfs5(int u,int f)
{
    int yq=W[u]-sd[u]+mi;
    int j=(yq<0?0:sl3[yq]);
    for(int i=lb3.he[u];i!=-1;i=lb3.r[i])
        sl3[lb3.z[i]+mi]+=1;
    for(int i=fr[u];i!=-1;i=ne[i])
    {
        if(v[i]!=f)
            dfs5(v[i],u);
    }
    j=(yq<0?0:sl3[yq])-j;
    jg[u]-=j;
}
void dfs6(int u,int f)
{
    int yq=W[u]+sd[u]+mi;
    int j=(yq<0?0:sl4[yq]);
    for(int i=lb4.he[u];i!=-1;i=lb4.r[i])
        sl4[lb4.z[i]+sd[u]+mi]+=1;
    for(int i=fr[u];i!=-1;i=ne[i])
    {
        if(v[i]!=f)
            dfs6(v[i],u);
    }
    j=(yq<0?0:sl4[yq])-j;
    jg[u]-=j;
}
int main()
{
    int N,M;
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++)
        fr[i]=lb1.he[i]=lb2.he[i]=lb3.he[i]=lb4.he[i]=-1;
    for(int i=0;i<N-1;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        addb(a,b);
        addb(b,a);
    }
    dfs1(1,-1);
    dfs2(1,-1,1);
    for(int i=1;i<=N;i++)
        scanf("%d",&W[i]);
    for(int i=0;i<M;i++)
    {
        int S,T;
        scanf("%d%d",&S,&T);
        lc[i]=lca(S,T);
        lb2.addlb(S,0);
        lb4.addlb(lc[i],sd[S]-sd[lc[i]]);
        lb1.addlb(T,sd[S]-sd[lc[i]]*2);
        lb3.addlb(lc[i],sd[S]-sd[lc[i]]*2);
        if(W[lc[i]]==sd[S]-sd[lc[i]])
            jg[lc[i]]+=1;
    }
    mi=-mi;
    dfs3(1,-1);
    dfs4(1,-1);
    dfs5(1,-1);
    dfs6(1,-1);
    for(int i=1;i<=N;i++)
        printf("%d ",jg[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lnzwz/p/11246699.html