bzoj 3572: [Hnoi2014] World Tree (Virtual Tree + Tree DP+LCA)

3572: [Hnoi 2014] World Tree

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1412  Solved: 784
[Submit][Status][Discuss]

Description

The World Tree is a tremendous tree. Its branches stretch out to make up the whole world. There are all kinds of races and creatures living here. They all believe in Alison, the goddess of absolute justice and fairness. In their belief, fairness is the fundamental cornerstone of making the world tree grow and run continuously.
The shape of the world tree can be described by a mathematical model: there are n races in the world tree, and the number of races is from 1 to n. They live in the colonies numbered 1 to n, respectively. The number of races is the same as that of their colonies. Some settlements are connected by two-way roads with a length of 1. The way to ensure the connection will form a tree structure, that is, all the settlements can reach each other, and there will be no rings. The distance between two settlements is defined as the length of the road connecting them; for example, if there is a road between settlements A and b, there is a road between B and c, because each road has a length of 1 and no loops, and the distance between lying a and C is 2.
In order to be fair, in the first year, the King of the World Tree needed to authorize m[i] ethnic settlements to be provisional. For a race x (where x is the race number), if the closest provisional Council to the race is y (where y is the residence number), race x will be subject to the jurisdiction of the Y Council (where y is the smallest provisional Council if there are multiple provisional councils at the same distance from the residence).
Now the King wants to know how many races will be managed by each provisional Council in q years after each year's authorization has been completed (the place where the Council resides will also be managed by the council). Now the task is assigned to you, a primate known for wisdom: the programmed ape. Please help the king to accomplish this task.

Input

The first action is a positive integer n, which represents the number of races in the world tree.
The next n-l line, with two positive integers x and y in each line, indicates that there is a pair of 1 length between the X and y settlements.
To the road. The next action is a positive integer q, indicating the number of years the king asked.
Next, q blocks, two lines for each block: q blocks, q blocks, q blocks, q blocks, q blocks, q blocks, q blocks, q blocks, q blocks, q blocks, q blocks, q blocks
The first act of block I is a positive integer m[i], which indicates the number of provisional deliberations authorized in year I.
The second behavior of block I is m[i] positive integers h[l], h[2],... h[m[i], denoting the number of settlements authorized to be provisional deliberations (guaranteed to be different from each other).

Output

The output contains q rows, m[i] integers of the I behavior, j(j=1, 2... The number of m[i] denotes the number of races administered by the provisional Council of the authorized settlement h[j] in the first year.

Sample Input

10
2 1
3 2
4 3
5 4
6 1
7 3
8 3
9 4
10 1
5
2
6 1
5
2 7 3 6 9
1
8
4
8 7 10 3
5
2 9 3 5 8

Sample Output

1 9
3 1 4 1 1
10
1 1 3 5
4 1 3 1 1

HINT

N<=300000, q<=300000,m[1]+m[2]+…+m[q]<=300000

Source

[Submit][Status][Discuss]

Problem Solution: Virtual Tree + Tree DP+LCA

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 300003
#define inf 1000000000
using namespace std;
int m,n,k,tot,sz,point[N],v[N*2],nxt[N*2],c[N*2],deep[N],pos[N],size[N],tp[N],ans[N];
int len[N][23],fa[N][23],mi[N],mark[N],a[N],st[N],top,sk[N],pre,tt,belong[N],b[N];
void add(int x,int y)
{
	tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; 
	tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void dfs(int x,int f)
{
	pos[x]=++sz; deep[x]=deep[f]+1; size[x]=1;
	for (int i=1;i<=20;i++) {
		if (deep[x]-mi[i]<0) break;
		fa[x][i]=fa[fa[x][i-1]][i-1];
		len[x][i]=len[x][i-1]+len[fa[x][i-1]][i-1];
	}
	for (int i=point[x];i;i=nxt[i]){
		if (v[i]==f) continue;
		len[v[i]][0]=1; fa[v[i]][0]=x;
		dfs(v[i],x);
		size[x]+=size[v[i]]; 
	}
}
int lca(int x,int y,int opt)
{
	if (x==0||y==0) return inf;
	if (deep[x]<deep[y]) swap(x,y);
	int k=deep[x]-deep[y]; int sum=0;
	for (int i=0;i<=20;i++)
	 if ((k>>i)&1) sum+=len[x][i],x=fa[x][i];
	if (x==y) if (opt==1) return y;
	          else return sum;
	for (int i=20;i>=0;i--)
	 if (fa[x][i]!=fa[y][i]) {
	 	sum+=len[x][i]; sum+=len[y][i];
	 	x=fa[x][i]; y=fa[y][i];
	 }
	sum+=len[x][0]; sum+=len[y][0]; 
	x=fa[x][0]; y=fa[y][0]; 
	if (opt==1) return x;
	else return sum;
}
int cmp(int x,int y){
	return pos[x]<pos[y];
}
int getson(int x,int k)
{
	if (k<=0) return x;
	for (int i=0;i<=19;i++) 
	 if ((k>>i)&1) x=fa[x][i];
	return x;
}
void build(int x,int y)
{
	if (x==y) return;
	tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=lca(x,y,0); tp[tot]=getson(y,deep[y]-deep[x]-1);
	//cout<<x<<" "<<y<<" "<<c[tot]<<" "<<tp[tot]<<endl;
}
void dp(int x)
{
	sk[x]=size[x]; st[++tt]=x;
	for (int i=point[x];i;i=nxt[i]){
		dp(v[i]); 
		sk[x]-=size[tp[i]];
		if (!belong[v[i]]) continue;
		int t1=lca(belong[v[i]],x,0); int t2=lca(belong[x],x,0);
		if (t1<t2||!belong[x]||t1==t2&&belong[v[i]]<belong[x])
		 belong[x]=belong[v[i]];
	}
}
void dp1(int x)
{
    for (int i=point[x];i;i=nxt[i]) {
    	if (belong[x]) {
    		int t1=lca(belong[v[i]],v[i],0); int t2=lca(v[i],belong[x],0);
    		if (t2<t1||!belong[v[i]]||t1==t2&&belong[x]<belong[v[i]])
    		 belong[v[i]]=belong[x];
		}
		dp1(v[i]);
	}
}
void calc(int x,int y,int c,int tp)
{
	if (c==1) return; 
	if (belong[x]==belong[y]) {
		int k=deep[y]-deep[x]-1; int x1=y; 
		for (int i=0;i<=19;i++) 
		 if ((k>>i)&1) x1=fa[x1][i];
		ans[belong[x]]+=size[x1]-size[y];
		return;
	}
	int t1=lca(belong[x],x,0);
	int t2=lca(belong[y],y,0);
	int len=t1+t2+c; int k=len/2;
	int a=belong[y];
	if (k*2==len) {
		if (belong[y]>belong[x]) k--;
	}
	for (int i=0;i<=19;i++)
	 if ((k>>i)&1) a=fa[a][i];
	ans[belong[y]]+=size[a]-size[y];
	ans[belong[x]]+=size[tp]-size[a];
}
void solve()
{
	scanf("%d",&k);
	for (int i=1;i<=k;i++) scanf("%d",&a[i]),mark[a[i]]=1;
	for (int i=1;i<=k;i++) belong[a[i]]=a[i],b[i]=a[i];
	sort(a+1,a+k+1,cmp);
	tot=0; tt=0; st[++tt]=1;
	for (int i=1;i<=k;i++) {
		int now=a[i]; int f=lca(st[tt],a[i],1);
		while (true) {
			if (deep[f]>=deep[st[tt-1]]) {
				build(f,st[tt--]);
				if (f!=st[tt]) st[++tt]=f;
				break;
			}
			build(st[tt-1],st[tt]); tt--;
		}
		if (now!=st[tt]) st[++tt]=now;
	}
	while (tt-1) build(st[tt-1],st[tt]),tt--;
	tt=0; dp(1); dp1(1); 
	for (int i=1;i<=tt;i++) {
	 for (int j=point[st[i]];j;j=nxt[j]) 
	  calc(st[i],v[j],c[j],tp[j]);
	 ans[belong[st[i]]]+=sk[st[i]];
    }
	for (int i=1;i<=k;i++) printf("%d ",ans[b[i]]); printf("\n");
	for (int i=1;i<=tt;i++) sk[st[i]]=0,mark[st[i]]=0,point[st[i]]=0,belong[st[i]]=0,ans[st[i]]=0;
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("my.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<n;i++) {
		int x,y; scanf("%d%d",&x,&y);
		add(x,y);
	}
	mi[0]=1;
	for (int i=1;i<=20;i++) mi[i]=mi[i-1]*2;
	dfs(1,0);
	scanf("%d",&m);
	tot=0;
	memset(point,0,sizeof(point));
	for (int i=1;i<=m;i++) solve();
}



Posted by eddy666 on Thu, 18 Apr 2019 01:33:33 -0700