luoguP1600 天天爱跑步

noip的难题,lca+dfs统计

思路其实不难,但是要代码实现0  0,有点烦(还是我太菜了!)。

调了好久,wa了好几发555.

#include<bits/stdc++.h>
using namespace std;
const int maxn=600010,N=600010;
int rs[maxn],rt[maxn],cnt=0,head[maxn],dep[maxn],f[maxn][20],dis[maxn],bucket[maxn*2],root=1,w[maxn],spn[maxn],ans[maxn];
bool visit[maxn];
struct edge{
    int to,next;
}e[maxn];
vector<int>v1[maxn],v2[maxn],v3[maxn];
//v1[i]以i为lca的起点,v2[i]以i为终的起点,v3[i]以i为lca的终点 
int lca(int a,int b){
    if(dep[a]<dep[b])swap(a,b);
    for(int i=0;i<20;++i)
    if(((dep[a]-dep[b])>>i)&1)a=f[a][i];
    if(a==b)return a;
    for(int i=19;i>=0;--i){
        if(f[a][i]!=f[b][i]){
            a=f[a][i];b=f[b][i];
        }
    }
    return f[a][0];
}
void add_edge(int s,int t){
    e[++cnt].next=head[s];e[cnt].to=t;head[s]=cnt;
    e[++cnt].next=head[t];e[cnt].to=s;head[t]=cnt;
}
int get_dis(int a,int b){
    return dis[a]+dis[b]-2*dis[lca(a,b)];
}
void dfs(int u){
    for(int i=head[u];i;i=e[i].next){
        if(!dep[e[i].to]){
            dis[e[i].to]=dis[u]+1;
            f[e[i].to][0]=u;
            dep[e[i].to]=dep[u]+1;
            dfs(e[i].to);
        }
    }
}
void dfs1(int u){
    visit[u]=1;
    int pre=bucket[w[u]+dep[u]+N];
    for(int i=head[u];i;i=e[i].next){
        if(!visit[e[i].to]){
            dfs1(e[i].to);
        }
    }
    bucket[N+dep[u]]+=spn[u];
    ans[u]+=bucket[w[u]+dep[u]+N]-pre;
    int len=v1[u].size();
    for(int i=0;i<len;++i){
        bucket[dep[v1[u][i]]+N]--;
    }
}
void dfs2(int u){
    visit[u]=1;
    int pre=bucket[w[u]-dep[u]+N];
    for(int i=head[u];i;i=e[i].next){
        if(!visit[e[i].to]){
            dfs2(e[i].to);
        }
    }
    for(int i=0;i<v2[u].size();++i){
        bucket[v2[u][i]+N]++;
    }
    ans[u]+=bucket[w[u]-dep[u]+N]-pre;
    for(int i=0;i<v3[u].size();++i){
        bucket[v3[u][i]+N]--;
    }
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n-1;++i){
        int s,t;
        scanf("%d%d",&s,&t);
        add_edge(s,t);
    }
    dep[root]=1;
    dfs(root);
    for(int j=0;j<20;++j){
        for(int i=1;i<=n;++i){
            if(f[i][j-1])f[i][j]=f[f[i][j-1]][j-1];
        }
    }
    for(int i=1;i<=n;++i)scanf("%d",&w[i]);
    for(int i=1;i<=m;++i){
        scanf("%d%d",&rs[i],&rt[i]);
        int l=lca(rs[i],rt[i]);
        spn[rs[i]]++;
        v1[l].push_back(rs[i]);
        v2[rt[i]].push_back(get_dis(rs[i],rt[i])-dep[rt[i]]);
        v3[l].push_back(get_dis(rs[i],rt[i])-dep[rt[i]]);
    }
    memset(visit,0,sizeof(visit));
    dfs1(root);
    memset(visit,0,sizeof(visit));
    dfs2(root);
    for(int i=1;i<=m;++i){
        int l=lca(rs[i],rt[i]);
        if(dep[rs[i]]==dep[l]+w[l])ans[l]--;
    }
    for(int i=1;i<=n;++i)printf("%d ",ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Dream-Runner/p/9418230.html