Uoj # 261 [] [] NOIP2016 love running every day

Everyone up and down can be divided into two parts, we will up and down the paths named as the first path and the second path.
The first number is the path of inquiry seeking after a certain point, the starting point depth dw, plus the depth of the starting point is the number of the second path of d + w's.
We open array record answer to each depth. For each path, we are below that point add, subtract above that point (note plus and minus are the starting point of the depth), asking it becomes a Child-giving tree and.
We can find the answer by dfs, dfs to a point when, after seeking an answer on depth, add tree complete sub-tree, new answer to the original point of difference is this the real answer before a note.
(On the second path is to extend up and then I lost the above paragraph, this also adds up from the root node n points)

These are my (read the solution to a problem) wrote last practice, however. . .
Anyway, the time complexity is O (nlogn), is not in dt or d + t is index, and then summed into a single point plus strand, and then combined or dsu segment tree on the list? Feeling so no brain a little?
I never wrote do not know right. . .

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define mxn 2000010
using namespace std;
int n,m,q,x,y,tot,head[mxn],p[mxn][21],dep[mxn],id[mxn],siz[mxn],a[mxn],ans[mxn];
int hd[mxn],nxt[mxn],cnt[mxn],sum[mxn],S[mxn],T[mxn],typ[mxn];
struct ed{int to,nxt;}edge[mxn<<1];
void addedge(int u,int v){
    edge[++m]=(ed){v,head[u]};head[u]=m;
    edge[++m]=(ed){u,head[v]};head[v]=m;
}
void dfs(int u,int fa,int d){
    p[u][0]=fa;dep[u]=d;siz[u]=1;id[u]=++tot;int v;
    for (int i=head[u];i;i=edge[i].nxt)
        if ((v=edge[i].to)!=fa)
            dfs(v,u,d+1),siz[u]+=siz[v];
}
int lca(int x,int y){
    if (dep[x]<dep[y]) {int t=x;x=y;y=t;}
    int k=log2(dep[x]);
    for (int i=k;i>=0;--i)
        if (dep[x]-(1<<i)>=dep[y]) x=p[x][i];
    if (x==y) return x;
    for (int i=k;i>=0;--i)
        if (p[x][i]!=p[y][i]) x=p[x][i],y=p[y][i];
    return p[x][0];
}
void dfs1(int u,int fa){//up
    int num=cnt[dep[u]+a[u]],v; 
    cnt[dep[u]]+=sum[u];
    for (int i=head[u];i;i=edge[i].nxt)
        if ((v=edge[i].to)!=fa) dfs1(v,u);
    ans[u]+=cnt[dep[u]+a[u]]-num;
    for (int j=hd[u];j;j=nxt[j]) --cnt[dep[S[j]]];
}
void dfs2(int u,int fa){//down add
    int num=cnt[dep[u]-a[u]],v;
    for (int j=hd[u];j;j=nxt[j]) ++cnt[dep[S[j]]];
    for (int i=head[u];i;i=edge[i].nxt)
        if ((v=edge[i].to)!=fa) dfs2(v,u);
    ans[u]+=cnt[dep[u]-a[u]]-num;
    cnt[dep[u]]-=sum[u];
}
void dfs3(int u,int fa){//down minus
    int num=cnt[dep[u]-a[u]],v;
    for (int j=hd[u];j;j=nxt[j]) ++cnt[dep[S[j]]];
    for (int i=head[u];i;i=edge[i].nxt)
        if ((v=edge[i].to)!=fa) dfs3(v,u);
    ans[u]-=cnt[dep[u]-a[u]]-num;
    cnt[dep[u]]-=sum[u];
}
int main()
{
    scanf("%d%d",&n,&q);
    for (int i=1;i<n;++i)
        scanf("%d%d",&x,&y),addedge(x,y);
    addedge(1,n+1);
    for (int i=1;i<n;++i)
        addedge(n+i,n+i+1);
    dfs(n*2,n*2,1);x=log2(n)+1;m=0;
    for (int j=1;j<=x;++j)
        for (int i=1;i<=n*2;++i)
            p[i][j]=p[p[i][j-1]][j-1];
    for (int i=1;i<=n;++i) scanf("%d",&a[i]);
    for (int i=1;i<=q;++i){
        scanf("%d%d",&x,&y);
        int z=lca(x,y),d=dep[z]*2-dep[x],k=log2(dep[x]-dep[z]+1),w=z;
        for (int j=k;j>=0;--j)
            if (dep[w]-(1<<j)>=d) w=p[w][j];
        S[++m]=x,T[m]=z,typ[m]=1;
        S[++m]=w,T[m]=y,typ[m]=2;
        S[++m]=w,T[m]=z,typ[m]=3;
    }
    for (int i=1;i<=m;++i)
        if (typ[i]==1)
            nxt[i]=hd[T[i]],hd[T[i]]=i,++sum[S[i]];
    dfs1(n*2,n*2);
    memset(cnt,0,sizeof(cnt));
    memset(sum,0,sizeof(sum));
    memset(hd,0,sizeof(hd));
    for (int i=1;i<=m;++i)
        if (typ[i]==2)
            nxt[i]=hd[T[i]],hd[T[i]]=i,++sum[S[i]];
    dfs2(n*2,n*2);
    memset(cnt,0,sizeof(cnt));
    memset(sum,0,sizeof(sum));
    memset(hd,0,sizeof(hd));
    for (int i=1;i<=m;++i)
        if (typ[i]==3)
            nxt[i]=hd[T[i]],hd[T[i]]=i,++sum[S[i]];
    dfs3(n*2,n*2);
    for (int i=1;i<=n;++i)
        printf("%d ",ans[i]);
    puts("");
    return 0;
}

Guess you like

Origin www.cnblogs.com/zzqtxdy/p/11488695.html