UOJ 261/bzoj 4719(LCA)(NOIP2016)(天天爱跑步)

传送门
NOIP 2016 D1T2
题解请参考:https://www.cnblogs.com/Yuzao/p/6918931.html
大概就是讨论出两种情况:
1.dep[q[i].st]=dep[u]+w[u]
2.dep[q[i].ed]-q[i].len=dep[u]-w[u]
然后用桶来记录值域,dfs两遍统计合法的贡献(子树内?子树外?),最后对于位于LCA的位置去重(两种情况都计算了它)即可。

#include
#include
#include
#include
#include
using namespace std;
const int N=3e5+4,M=3e5+4;
int n,m,head[N],etot=0;
struct EDGE {
    int v,nxt;
}e[N<<1];
int w[N],ans[N],f[21][N],dep[N],t[N<<1],g[N<<1],mark[N];
vector<int > c1[N],c2[N],c3[N];
struct Node {
    int st,ed,len,lca;
}q[M];
inline int read() {
    int x=0;char c=getchar();
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x;
}
inline void adde(int u,int v) {
    e[etot].nxt=head[u],e[etot].v=v,head[u]=etot++;
    e[etot].nxt=head[v],e[etot].v=u,head[v]=etot++;
}
void pre_dfs(int p,int fa) {
    f[0][p]=fa,dep[p]=dep[fa]+1;
    for (int j=1;j<21;++j) f[j][p]=f[j-1][f[j-1][p]];
    for (int i=head[p];~i;i=e[i].nxt) {
        int v=e[i].v;
        if (v^fa) pre_dfs(v,p);
    }
}
inline int qlca(int x,int y) {
    if (dep[x]y]) x^=y^=x^=y;
    int t=dep[x]-dep[y];
    for (int i=0;i<21;++i)
        if (t&(1<x=f[i][x];
    if (x==y) return x;
    for (int i=20;~i;--i)
        if (f[i][x]^f[i][y]) x=f[i][x],y=f[i][y];
    return f[0][x];
}
void dfs1(int p,int fa) {
    int now=dep[p]+w[p],pre=t[now];
    for (int i=head[p];~i;i=e[i].nxt) {
        int v=e[i].v;
        if (v^fa) dfs1(v,p);
    }
    t[dep[p]]+=mark[p];
    ans[p]+=t[now]-pre;
    for (int i=0;iint p,int fa) {
    int now=dep[p]-w[p]+N,pre=g[now];
    for (int i=head[p];~i;i=e[i].nxt) {
        int v=e[i].v;
        if (v^fa) dfs2(v,p);
    }
    for (int i=0;ifor (int i=0;iint main() {
//  freopen("UOJ 261.in","r",stdin);
    memset(head,-1,sizeof(head));
    n=read(),m=read();
    for (register int i=1;iint u=read(),v=read();
        adde(u,v);
    }
    pre_dfs(1,0);
    for (register int i=1;i<=n;++i) w[i]=read();
    for (register int i=1;i<=m;++i) {
        q[i].st=read(),q[i].ed=read();
        q[i].lca=qlca(q[i].st,q[i].ed),q[i].len=dep[q[i].st]+dep[q[i].ed]-(dep[q[i].lca]<<1);
    }
    for (register int i=1;i<=m;++i) {
        ++mark[q[i].st];
        c1[q[i].lca].push_back(dep[q[i].st]);
    }
    dfs1(1,0);
    for (register int i=1;i<=m;++i) {
        c2[q[i].ed].push_back(dep[q[i].ed]-q[i].len+N);
        c3[q[i].lca].push_back(dep[q[i].ed]-q[i].len+N);
    }
    dfs2(1,0);
    for (register int i=1;i<=m;++i)
        if (dep[q[i].st]==dep[q[i].lca]+w[q[i].lca]) --ans[q[i].lca];
    for (register int i=1;i<=n;++i) printf("%d ",ans[i]);
    return 0;
}

你可能感兴趣的:(图论)