如果没有时间的限制,这题就是对每个点iii,求经过iii的路径数,用树上差分解决即可:
枚举路径x→y{x\to y\{x→y{
a[x]+=1;a[y]+=1;a[x]+=1;a[y]+=1;a[x]+=1;a[y]+=1;
a[lca(x,y)]−=1;a[fa[lca(x,y)]]−=2;a[lca(x,y)]-=1;a[fa[lca(x,y)]]-=2;a[lca(x,y)]−=1;a[fa[lca(x,y)]]−=2;
}\}}
枚举点i{i\{i{
经过iii的路径数 = 以iii为根的子树中aaa的和
}\}}
(用树状数组实现)
考虑加上时间限制怎么做:
我们把每条路径x→yx\to yx→y拆成上行段和下行段。
-
若点iii在x→yx\to yx→y的上行段上,
iii点的观察员看到从xxx出发跑到yyy的玩家,当且仅当
dep[x]−dep[i]=w[i]dep[x]-dep[i]=w[i]dep[x]−dep[i]=w[i]即dep[i]+w[i]=dep[x]dep[i]+w[i]=dep[x]dep[i]+w[i]=dep[x] -
若点iii在x→yx\to yx→y的下行段上,
iii点的观察员看到从xxx出发跑到yyy的玩家,当且仅当
dep[x]+dep[y]−2dep[lca(x,y)]−(dep[y]−dep[i])=w[i]dep[x]+dep[y]-2dep[lca(x,y)]-(dep[y]-dep[i])=w[i]dep[x]+dep[y]−2dep[lca(x,y)]−(dep[y]−dep[i])=w[i]
即dep[i]−w[i]=2dep[lca(x,y)]−dep[x]dep[i]-w[i]=2dep[lca(x,y)]-dep[x]dep[i]−w[i]=2dep[lca(x,y)]−dep[x]
对于路径x→yx\to yx→y,我们将其拆成 上行段p:x→lca(x,y)p:x\to lca(x,y)p:x→lca(x,y)在xxx方向上的儿子,下行段q:lca(x,y)→yq:lca(x,y)\to yq:lca(x,y)→y,并记v[p]=dep[x]v[p]=dep[x]v[p]=dep[x],v[q]=2dep[lca(x,y)]−dep[x]v[q]=2dep[lca(x,y)]-dep[x]v[q]=2dep[lca(x,y)]−dep[x]
对于点iii,我们记vp[i]=dep[i]+w[i]v_p[i]=dep[i]+w[i]vp[i]=dep[i]+w[i],vq[i]=dep[i]−w[i]v_q[i]=dep[i]-w[i]vq[i]=dep[i]−w[i]
那么iii点的观察员看到的玩家数 = ∑\sum∑经过iii且满足v[p]=vp[i]v[p]=v_p[i]v[p]=vp[i]的上行段ppp的数量 + ∑\sum∑经过iii且满足v[q]=vq[i]v[q]=v_q[i]v[q]=vq[i]的下行段qqq的数量
先把点按vp[i]v_p[i]vp[i]排序,把上行段按v[p]v[p]v[p]排序,按树上差分的套路计算上行段的贡献。
再把点按vq[i]v_q[i]vq[i]排序,把下行段按v[q]v[q]v[q]排序,按树上差分的套路计算下行段的贡献。
如此即可得到最终答案。
#include<iostream>
#include<cstdio>
#include<stack>
#include<algorithm>
using namespace std;
const int N=1e6+10;
struct Edge{int v,nxt;
}edge[N<<1];
int n,m,w[N],cnt,head[N],ans[N];
int ind,dfn[N],siz[N],dep[N],fa[N][20];
struct Query{int nd,x;friend bool operator < (Query a,Query b){return a.x<b.x;}
}a[N<<1];
struct Data{int d,u,x;friend bool operator < (Data a,Data b){return a.x<b.x;}
}b[2][N];
int tot[2];
stack<Data> s;
void addedge(int u,int v){edge[++cnt].v=v;edge[cnt].nxt=head[u];head[u]=cnt;
}
void dfs(int u){dfn[u]=++ind;siz[u]=1;for(int i=1;i<=19;i++)fa[u][i]=fa[fa[u][i-1]][i-1];for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v==fa[u][0]) continue;fa[v][0]=u;dep[v]=dep[u]+1;dfs(v);siz[u]+=siz[v];}
}
int LCA(int u,int v){if(dep[u]<dep[v]) swap(u,v);int diff=dep[u]-dep[v];for(int i=19;i>=0;i--){if(diff&(1<<i)) u=fa[u][i];}if(u==v) return u;for(int i=19;i>=0;i--){if(fa[u][i]!=fa[v][i]){u=fa[u][i];v=fa[v][i];}}return fa[u][0];
}
int c[N];
int lowbit(int x){return x&(-x);}
void add(int x,int v){if(!x) return;for(int i=x;i<=n;i+=lowbit(i)) c[i]+=v;
}
int sum(int x){int res=0;for(int i=x;i;i-=lowbit(i)) res+=c[i];return res;
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);}dep[1]=1;dfs(1);for(int i=1;i<=n;i++){scanf("%d",&w[i]);a[i]=(Query){i,dep[i]+w[i]};a[i+n]=(Query){i,dep[i]-w[i]};}sort(a+1,a+n+1);sort(a+n+1,a+2*n+1);for(int i=1;i<=m;i++){int s,t,lca;scanf("%d%d",&s,&t);lca=LCA(s,t);if(s==lca){b[1][++tot[1]]=(Data){t,s,dep[s]};}else if(t==lca){b[0][++tot[0]]=(Data){s,t,dep[s]};}else{int son=s;for(int i=19;i>=0;i--){if(dep[fa[son][i]]>dep[lca]) son=fa[son][i];}b[0][++tot[0]]=(Data){s,son,dep[s]};b[1][++tot[1]]=(Data){t,lca,2*dep[lca]-dep[s]};}}sort(b[0]+1,b[0]+tot[0]+1);sort(b[1]+1,b[1]+tot[1]+1);int p=1;for(int i=1;i<=n;i++){if(a[i].x!=a[i-1].x){while(!s.empty()){Data tmp=s.top();s.pop();add(dfn[fa[tmp.u][0]],1);add(dfn[tmp.d],-1);}}for(;p<=tot[0]&&b[0][p].x<=a[i].x;p++){if(a[i].x!=a[i-1].x&&b[0][p].x==a[i].x){Data tmp=b[0][p];add(dfn[fa[tmp.u][0]],-1);add(dfn[tmp.d],1);s.push(tmp);}}ans[a[i].nd]+=sum(dfn[a[i].nd]+siz[a[i].nd]-1)-sum(dfn[a[i].nd]-1);}while(!s.empty()){Data tmp=s.top();s.pop();add(dfn[fa[tmp.u][0]],1);add(dfn[tmp.d],-1);}p=1;for(int i=n+1;i<=2*n;i++){if(a[i].x!=a[i-1].x){while(!s.empty()){Data tmp=s.top();s.pop();add(dfn[fa[tmp.u][0]],1);add(dfn[tmp.d],-1);}}for(;p<=tot[1]&&b[1][p].x<=a[i].x;p++){if(a[i].x!=a[i-1].x&&b[1][p].x==a[i].x){Data tmp=b[1][p];add(dfn[fa[tmp.u][0]],-1);add(dfn[tmp.d],1);s.push(tmp);}}ans[a[i].nd]+=sum(dfn[a[i].nd]+siz[a[i].nd]-1)-sum(dfn[a[i].nd]-1);}for(int i=1;i<=n;i++)printf("%d ",ans[i]);return 0;
}