hanmo0321 @ 2020-11-03 17:22:17
#include<bits/stdc++.h>
using namespace std;
int n,m,edgenum,vet[600000],Next[600000],head[300000],dep[300000],Log[300000],f[300000][20];
int U[300000],V[300000],LCA[300005],in[300005],out[300005],dfs_clock,maxd,num,rt[300005];
int tree[10000005],ls[10000005],rs[10000005],t[300000],ans[300005];
void addedge(int u,int v){
vet[++edgenum]=v;
Next[edgenum]=head[u];
head[u]=edgenum;
}
void dfs(int u,int fa){
maxd=max(maxd,dep[u]);
in[u]=++dfs_clock;
for(int i=1;i<=Log[n];i++) f[u][i]=f[f[u][i-1]][i-1];
for(int e=head[u];e;e=Next[e]){
int v=vet[e];
if(v!=fa){
f[v][0]=u;
dep[v]=dep[u]+1;
dfs(v,u);
}
}
out[u]=dfs_clock;
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
for(int i=Log[n];i>=0;i--)
if(dep[f[u][i]]>=dep[v]) u=f[u][i];
if(u==v) return u;
for(int i=Log[n];i>=0;i--)
if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
return f[u][0];
}
void add(int p,int l,int r,int x,int y){
if(l==r){
tree[p]+=y;
return;
}
int mid=(l+r)>>1;
if(x<=mid){
if(!ls[p]) ls[p]=++num;
add(ls[p],l,mid,x,y);
}else{
if(!rs[p]) rs[p]=++num;
add(rs[p],mid+1,r,x,y);
}
tree[p]=tree[ls[p]]+tree[rs[p]];
}
int ask(int p,int l,int r,int x,int y){
if(l==x && r==y) return tree[p];
int mid=(l+r)>>1;
if(y<=mid){
if(ls[p]) return ask(ls[p],l,mid,x,y);
else return 0;
}else if(x>mid){
if(rs[p]) return ask(rs[p],mid+1,r,x,y);
else return 0;
}else{
int ans=0;
if(ls[p]) ans+=ask(ls[p],l,mid,x,mid);
if(rs[p]) ans+=ask(rs[p],mid+1,r,mid+1,y);
return ans;
}
}
int main(){
scanf("%d%d",&n,&m);
Log[0]=-1;
for(int i=1;i<=n;i++) Log[i]=Log[i>>1]+1;
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
for(int i=1;i<=n;i++) scanf("%d",&t[i]);
dep[1]=1;
// cout<<__LINE__<<endl;
dfs(1,-1);
// cout<<__LINE__<<endl;
for(int i=1;i<=m;i++) scanf("%d%d",&U[i],&V[i]);
for(int i=1;i<=m;i++) LCA[i]=lca(U[i],V[i]);
for(int i=1;i<=maxd;i++) rt[i]=++num;
// cout<<__LINE__<<endl;
for(int i=1;i<=m;i++){
add(rt[dep[U[i]]],1,n,in[U[i]],1);
if(LCA[i]!=1) add(rt[dep[U[i]]],1,n,in[f[LCA[i]][0]],-1);
}
// cout<<__LINE__<<endl;
for(int i=1;i<=n;i++) ans[i]+=ask(rt[dep[i]+t[i]],1,n,in[i],out[i]);
// for(int i=1;i<n;i++) printf("%d ",ans[i]);printf("%d\n",ans[n]);
// cout<<__LINE__<<endl;
for(int i=1;i<=num;i++) ls[i]=rs[i]=tree[i]=0;
num=0;
for(int i=1;i<=maxd+n+n;i++) rt[i]=++num;
for(int i=1;i<=m;i++){
int D=dep[U[i]]-dep[LCA[i]]*2+n+n;
add(rt[D],1,n,in[V[i]],1);
add(rt[D],1,n,in[LCA[i]],-1);
}
for(int i=1;i<=n;i++) ans[i]+=ask(rt[t[i]-dep[i]+n+n],1,n,in[i],out[i]);
for(int i=1;i<n;i++) printf("%d ",ans[i]);printf("%d\n",ans[n]);
// for(int i=1;i<=n;i++) printf("%d: %d %d\n",i,in[i],out[i]);
// for(int i=1;i<=m;i++) printf("%d %d %d\n",U[i],V[i],LCA[i]);
return 0;
}
用的是线段树动态开点,第13个点RE,数组开到两千万也没用,不清楚是不是爆栈了。如果爆栈了怎么改呢?
by ¶凉笙 @ 2021-06-11 19:15:25
luogu不存在爆栈现象的。
by uniqueharry @ 2021-06-15 14:45:29
@hanmo0321 这边建议把所有的数组都开成 6e5 那么大,(除了您的tree和ls可能有特殊用处最好不要改