您的位置:首页 > 其它

【BZOJ】3572: [Hnoi2014]世界树【虚树DP】

2015-04-21 12:48 302 查看
传送门:3572: [Hnoi2014]世界树

my code:

#include <stdio.h>
#include <string.h>
#include <set>
#include <algorithm>
using namespace std ;

typedef long long LL ;
typedef unsigned long long ULL ;
typedef pair < int , int > pii ;

#define rep( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )
#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define clr( a , x ) memset ( a , x , sizeof a )
#define mp make_pair
#define st first 
#define ed second 

const int MAXN = 300005 ;
const int MAXE = 600005 ;
const int LOG = 20 ;
const int INF = 0x3f3f3f3f ;

struct Edge {
	int v , n ;
	Edge () {}
	Edge ( int v , int n ) : v ( v ) , n ( n ) {}
} ;

Edge E[MAXE] ;
int H[MAXN] , cntE ;
int idx[MAXN] , dfs_clock ;
int S[MAXN] , top ;
int f[MAXN][LOG] ;
int tree[MAXN] ;
int node[MAXN] ;
int dep[MAXN] ;
int siz[MAXN] ;
int dis[MAXN] ;
int val[MAXN] ;
int ans[MAXN] ;
int fa[MAXN] ;
pii G[MAXN] ;
int n , m ;

void init () {
	cntE = 0 ;
	dfs_clock = 0 ;
	clr ( H , -1 ) ;
}

void addedge ( int u , int v ) {
	E[cntE] = Edge ( v , H[u] ) ;
	H[u] = cntE ++ ;
}

void dfs ( int u ) {
	idx[u] = ++ dfs_clock ;
	siz[u] = 1 ;
	for ( int i = H[u] ; ~i ; i = E[i].n ) {
		int v = E[i].v ;
		if ( v == f[u][0] ) continue ;
		f[v][0] = u ;
		dep[v] = dep[u] + 1 ;
		rep ( j , 1 , LOG ) f[v][j] = f[f[v][j - 1]][j - 1] ;
		dfs ( v ) ;
		siz[u] += siz[v] ;
	}
}

int find ( int x , int depth ) {
	rev ( i , LOG - 1 , 0 ) if ( dep[x] - ( 1 << i ) >= depth ) x = f[x][i] ;
	return x ;
}

int get_lca ( int x , int y ) {
	if ( dep[x] < dep[y] ) swap ( x , y ) ;
	x = find ( x , dep[y] ) ;
	if ( x == y ) return x ;
	rev ( i , LOG - 1 , 0 ) if ( f[x][i] != f[y][i] ) {
		x = f[x][i] ;
		y = f[y][i] ;
	}
	return f[x][0] ;
}

void read_graph () {
	int u , v ;
	rep ( i , 1 , n ) {
		scanf ( "%d%d" , &u , &v ) ;
		addedge ( u , v ) ;
		addedge ( v , u ) ;
	}
}

bool cmp ( const int& x , const int& y ) {
	return idx[x] < idx[y] ;
}

void deal () {
	int cnt , tot ;
	scanf ( "%d" , &cnt ) ;
	rep ( i , 0 , cnt ) {
		scanf ( "%d" , &node[i] ) ;
		tree[i] = node[i] ;
		ans[node[i]] = 0 ;
		G[node[i]] = mp ( 0 , node[i] ) ;
	}
	tot = cnt ;
	sort ( tree , tree + cnt , cmp ) ;
	S[top = 1] = tree[0] ;
	fa[tree[0]] = 0 ;
	rep ( i , 1 , cnt ) {
		int tmp = tree[i] , lca = get_lca ( S[top] , tmp ) ;
		fa[tmp] = lca ;
		while ( top && dep[lca] < dep[S[top]] ) {
			if ( dep[S[top - 1]] <= dep[lca] ) fa[S[top]] = lca ;
			-- top ;
		}
		if ( S[top] != lca ) {
			fa[lca] = S[top] ;
			S[++ top] = lca ;
			tree[tot ++] = lca ;
			G[lca] = mp ( INF , 0 ) ;
		}
		S[++ top] = tmp ;
	}
	sort ( tree , tree + tot , cmp ) ;
	rep ( i , 0 , tot ) {
		int t = tree[i] , p = fa[t] ;
		val[t] = siz[t] ;
		dis[t] = dep[t] - dep[p] ;
	}
	rev ( i , tot - 1 , 1 ) {
		int t = tree[i] , p = fa[t] ;
		G[p] = min ( G[p] , mp ( G[t].st + dis[t] , G[t].ed ) ) ;
	}
	rep ( i , 1 , tot - 1 ) {
		int t = tree[i] , p = fa[t] ;
		G[t] = min ( G[t] , mp ( G[p].st + dis[t] , G[p].ed ) ) ;
	}
	rev ( i , tot - 1 , 0 ) {
		int t = tree[i] , p = fa[t] , x = find ( t , dep[p] + 1 ) , sum = siz[x] - siz[t] ;
		ans[G[t].ed] += val[t] ;
		if ( !i ) {
			ans[G[t].ed] += n - siz[t] ;
			continue ;
		}
		val[p] -= siz[x] ;
		if ( G[p].ed == G[t].ed ) ans[G[t].ed] += sum ;
		else {
			int d = G[t].st + G[p].st + dis[t] - 1 ;
			int mid = dep[t] - ( d / 2 - G[t].st ) + ( d % 2 == 1 && G[t].ed < G[p].ed ? -1 : 0 ) ;
			int y = siz[find ( t , mid )] - siz[t] ;
			ans[G[t].ed] += y ;
			ans[G[p].ed] += sum - y ;
		}
	}
	rep ( i , 0 , cnt ) printf ( "%d " , ans[node[i]] ) ;
	printf ( "\n" ) ;
}

void solve () {
	init () ;
	read_graph () ;
	dfs ( 1 ) ;
	scanf ( "%d" , &m ) ;
	rep ( i , 0 , m ) deal () ;
}

int main () {
	while ( ~scanf ( "%d" , &n ) ) solve () ;
	return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: