[NOIP 2016D2T2/Luogu P1600] 天天爱跑步 (LCA+差分)

待填坑

Code

//Luogu P1600 天天爱跑步
//Apr,4th,2018
//树上差分+LCA
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
long long read()
{
    long long x=0,f=1; char c=getchar();
    while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
const int N=300000+100;
vector <int> e[N];
int n,m;
int fa[N][21],depth[N],T[N];
void dfs(int now)
{
    for(int i=1;i<=20;i++)
        fa[now][i]=fa[fa[now][i-1]][i-1];
    for(int i=0;i<int(e[now].size());i++)
        if(depth[e[now][i]]==0)
        {
            depth[e[now][i]]=depth[now]+1;
            fa[e[now][i]][0]=now;
            dfs(e[now][i]);
        }
}
int LCA(int x,int y)
{
    if(depth[x]<depth[y]) 
        swap(x,y);
    for(int i=20;i>=0;i--)
        if(depth[fa[x][i]]>=depth[y])
            x=fa[x][i];
    if(x==y) return x;
    for(int i=20;i>=0;i--)
        if(fa[x][i]!=fa[y][i])
            x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
struct mark
{
    int count,num;
};
vector <mark> mk1[N],mk2[N];
int ans[N],MK1[N*10],MK2[N*10];
void dfs2(int now)
{
    int rec1=MK1[T[now]+depth[now]],rec2=MK2[T[now]-depth[now]+2*N];
    for(int i=0;i<int(e[now].size());i++)
        if(depth[e[now][i]]>depth[now])
            dfs2(e[now][i]);
    for(int i=0;i<int(mk1[now].size());i++)
        MK1[mk1[now][i].num]+=mk1[now][i].count;
    for(int i=0;i<int(mk2[now].size());i++)
        MK2[mk2[now][i].num]+=mk2[now][i].count;                
    ans[now]+=MK1[T[now]+depth[now]]-rec1;
    ans[now]+=MK2[T[now]-depth[now]+2*N]-rec2;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        e[i].reserve(4);
    for(int i=1;i<n;i++)
    {
        int s=read(),t=read();
        e[s].push_back(t);
        e[t].push_back(s);
    }
    for(int i=1;i<=n;i++)
        T[i]=read();
        
    depth[1]=1;
    dfs(1);
    
    for(int i=1;i<=m;i++)
    {
        int s=read(),t=read(),lca=LCA(s,t);
        mk1[s].push_back((mark){1,depth[s]});
        mk2[t].push_back((mark){1,depth[s]-2*depth[lca]+2*N});
        mk1[lca].push_back((mark){-1,depth[s]});
        mk2[fa[lca][0]].push_back((mark){-1,depth[s]-2*depth[lca]+2*N});
    }
    dfs2(1);
    
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i]);
    return 0;
}
View Code

 

posted @ 2018-04-08 19:28  GoldenPotato  阅读(130)  评论(0编辑  收藏  举报