[NOIP2016] I love running every day (bpd)

The meaning of problems

Given a right side of a tree, the right point of v, the m given path from s to t, for each point, seeking \ (ans_i = \ Sigma_ {j = 1} ^ m [dist (s_j , i) == v [i] ] \)

Thinking

There are two possible approaches, one is the full path added to the list, and then ask each point \ (ANS \) , and the other is a one plus path, each time seeking contributions. The use of this question is the first

For each path, the \ (s-> t \) path split \ (S-> LCA-> T \) , \ (S-> LCA \) to the left of the path, \ (LCA-> T \ ) for the right path, the path to a point on the left \ (I \) , a left path if and only if it contributes \ (DEP [S] -dep [I] == V [I] \) , the \ ( I \) move the item to the side, there are \ (DEP [S] == DEP [I] + V [I] \) , so that all paths can be added to the list and then seek \ (I \) contribution point. Similarly there is a right path \ (dep [s] -2 * dep [lca] == v [i] -dep [i] \)

\ (DFS \) whole pieces tree when seeking from the back up \ (ANS \) , back to a point encountered \ (I \) , was added to it as the \ (s / t \) of the right and left paths, seek a \ (ANS \) , it is subtracted to exit \ (lca \) the path to the left and right,Then the sample had not found

(Assuming that the current in order to \ (u \) subtree is the root of the \ (the DFS \) ) because \ (u \) is a Ke subtree \ (v \) when in, \ (u \) Other inside the sub-tree path has also been recorded, then it will not lead to a path on top of it points to contribute.
Solution: Because demand is to meet the above two constraints of several paths, then enter a recursive \ (v \) before adding sub-tree inside route, subtract the first number of this time to meet the constraints of the path, thus ensuring the contribution is \ (v \) path inside the sub-tree starting

Further, if the \ (I \) is the path \ (LCA \) words may be counted twice (once for each right and left paths), so minus 1, i.e. when satisfying \ (v [lca] == dep [s] - dep [lca] \) when minus 1

Code:

#include<bits/stdc++.h>
#define N 900005
#define M 300005
using namespace std;
const int temp = 300000;
int n,m;
int dep[M],w[M],fa[M][18],ans[M];
int lsum[N],rsum[N];//桶 
vector<int> L[M],R[M];//lca在上面,出 
vector<int> l[M],r[M];//s,t在下面,入 
struct Edge
{
    int next,to;
}edge[M<<1];int head[M],cnt=1;
void add_edge(int from,int to)
{
    edge[++cnt].next=head[from];
    edge[cnt].to=to;
    head[from]=cnt;
}
template <class T>
void read(T &x)
{
    char c;int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}
void dfs(int rt)
{
    dep[rt]=dep[fa[rt][0]]+1;
    for(int i=head[rt];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa[rt][0]) continue;
        fa[v][0]=rt;
        for(int i=1;i<18;++i) fa[v][i]=fa[fa[v][i-1]][i-1];
        dfs(v);
    }
}
int lca(int x,int y)
{
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=17;i>=0;--i) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    if(x==y) return x;
    for(int i=17;i>=0;--i) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
void DFS(int rt)
{
    ans[rt]-=lsum[dep[rt]+w[rt]+temp]+rsum[w[rt]-dep[rt]+temp];
    for(int i=head[rt];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa[rt][0]) continue;
        DFS(v);
    }
    //加入rt
    for(int i=0;i<(int)l[rt].size();++i)
    {
        int val=l[rt][i]+temp;
        ++lsum[val];
    }
    for(int i=0;i<(int)r[rt].size();++i)
    {
        int val=r[rt][i]+temp;
        ++rsum[val];
    }
    ans[rt]+=lsum[dep[rt]+w[rt]+temp]+rsum[w[rt]-dep[rt]+temp];
    //删除以rt为lca的链 
    for(int i=0;i<(int)L[rt].size();++i)
    {
        int val=L[rt][i]+temp;
        --lsum[val];
    }
    for(int i=0;i<(int)R[rt].size();++i)
    {
        int val=R[rt][i]+temp;
        --rsum[val];
    }   
}
int main()
{
    read(n);read(m);
    for(int i=1;i<n;++i)
    {
        int x,y;
        read(x);read(y);
        add_edge(x,y);
        add_edge(y,x);
    }
    dfs(1);
    for(int i=1;i<=n;++i) read(w[i]);
    for(int i=1;i<=m;++i)
    {
        int S,T;
        read(S);read(T);
        int lc=lca(S,T);
        if(w[lc]==dep[S]-dep[lc]) ans[lc]--;
        L[lc].push_back(dep[S]);
        R[lc].push_back(dep[S]-2*dep[lc]);
        l[S].push_back(dep[S]);
        r[T].push_back(dep[S]-2*dep[lc]);
    }
    DFS(1);
    for(int i=1;i<=n;++i) printf("%d ",ans[i]); 
    return 0;
}

Guess you like

Origin www.cnblogs.com/Chtholly/p/11370320.html