记录编号 281025 评测结果 AAAAAAAAAA
题目名称 [HNOI 2014]世界树 最终得分 100
用户昵称 GravatarTenderRun 是否通过 通过
代码语言 C++ 运行时间 2.402 s
提交时间 2016-07-11 00:07:06 内存使用 46.09 MiB
显示代码纯文本
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=300010;
const int INF=1000000000;
int cntE,fir[maxn],to[maxn*2],nxt[maxn*2];

void addedge(int a,int b){
    nxt[++cntE]=fir[a];
    fir[a]=cntE;
    to[cntE]=b;
}

int fa[maxn][20],dep[maxn];
int sz[maxn],son[maxn];
void DFS(int x){
    sz[x]=1;
    for(int k=0;
		(fa[x][k+1]=fa[fa[x][k]][k]);
			k++);
    for(int i=fir[x];i;i=nxt[i])
		if(to[i]!=fa[x][0]){
			fa[to[i]][0]=x;
			dep[to[i]]=dep[x]+1;
			DFS(to[i]);
			sz[x]+=sz[to[i]];
			if(sz[to[i]]>sz[son[x]])
				son[x]=to[i];
    	}
}

int rID[maxn],tot;
int top[maxn],ID[maxn];

void DFS(int x,int tp){
	top[x]=tp;
    ID[x]=++tot;rID[tot]=x;
    if(son[x])DFS(son[x],tp);
    for(int i=fir[x];i;i=nxt[i])
		if(to[i]!=fa[x][0]&&to[i]!=son[x])
			DFS(to[i],to[i]);
}

int Lca(int x,int y){
    while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])
			swap(x,y);
		x=fa[top[x]][0];
    }
    if(dep[x]<dep[y])
		swap(x,y);
    return y;  
}

int Get(int y,int d){
    while(dep[top[y]]>d)
		y=fa[top[y]][0];
    int dis=dep[y]-d;        
    for(int i=20;i>=0;i--)
		if(dis>>i&1)y=fa[y][i];
    return y; 
}

pair<int,int>g[maxn];
int h[maxn],mem[maxn];
int ans[maxn],t[maxn];
int st[maxn],pre[maxn],val[maxn];
int n,m,Q,tp;
int main(){
#ifndef ONLINE_JUDGE
	freopen("worldtree.in","r",stdin);
	freopen("worldtree.out","w",stdout);
#endif	
    scanf("%d",&n);
    for(int i=1,a,b;i<n;i++){
		scanf("%d%d",&a,&b);
		addedge(a,b);
		addedge(b,a);
    }
    dep[1]=1;
    DFS(1);DFS(1,1);
    scanf("%d",&Q);
    while(Q--){
		scanf("%d",&m);tot=0;
		for(int i=1;i<=m;i++){
			scanf("%d",&h[i]);mem[i]=h[i];
			g[h[i]]=make_pair(0,h[i]);
			ans[h[i]]=0;h[i]=ID[h[i]];
			t[++tot]=h[i];
		}
		sort(h,h+m+1);tp=0;
		for(int i=1;i<=m;i++)
			h[i]=rID[h[i]];
		for(int i=1;i<=m;i++){
			if(i==1)
				pre[st[++tp]=h[i]]=0;
			else{
				int p=h[i],lca=Lca(p,st[tp]);
				for(;dep[st[tp]]>dep[lca];tp--)
					if(dep[st[tp-1]]<=dep[lca])
				pre[st[tp]]=lca;
				if(st[tp]!=lca){      
					t[++tot]=ID[lca];
					g[lca]=make_pair(INF,0);
					pre[lca]=st[tp];
					st[++tp]=lca;
				}
			pre[p]=st[tp];
			st[++tp]=p;
			}        
		}       
		sort(t+1,t+tot+1);
		for(int i=1;i<=tot;i++)
			t[i]=rID[t[i]];
		for(int i=1;i<=tot;i++){
			int p=t[i],f=pre[p];
			if(i==1)val[p]=n;
			else{
				val[p]=sz[p];
				val[f]-=sz[Get(p,dep[f]+1)];
			}
		}
		for(int i=tot;i>1;i--){
			int p=t[i],f=pre[p],w=dep[p]-dep[f];
			g[f]=min(g[f],make_pair(g[p].first+w,g[p].second));
		}
		for(int i=2;i<=tot;i++){
			int p=t[i],f=pre[p],w=dep[p]-dep[f];
			g[p]=min(g[p],make_pair(g[f].first+w,g[f].second));
		} 
		ans[g[t[1]].second]+=val[t[1]];
		for(int i=2;i<=tot;i++){
			int p=t[i],f=pre[p];
			ans[g[p].second]+=val[p];
			if(g[p].second==g[f].second)
				ans[g[p].second]+=sz[Get(p,dep[f]+1)]-sz[p];
			else{
				int da=dep[f],db=dep[p],mid;
				if(g[f].first>g[p].first)
					db-=g[f].first-g[p].first;
				if(g[f].first<g[p].first)
					da+=g[p].first-g[f].first;
				mid=(da+db+1)/2;
				mid+=((db-da)%2==0&&g[f].second<g[p].second)?1:0;
				int q=Get(p,mid);
				ans[g[p].second]+=sz[q]-sz[p];
				ans[g[f].second]+=sz[Get(p,dep[f]+1)]-sz[q];
			}        
		} 
		for(int i=1;i<=m;i++){
			printf("%d ",ans[mem[i]]);
			ans[mem[i]]=0;
		}
		printf("\n");      
    }
    return 0;
}