95RE,救救孩子……
查看原帖
95RE,救救孩子……
104381
hanmo0321楼主2020/11/3 17:22
#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,数组开到两千万也没用,不清楚是不是爆栈了。如果爆栈了怎么改呢?

2020/11/3 17:22
加载中...