Description
世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界。在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息、持续运转的根本基石。
世界树的形态可以用一个数学模型来描述:世界树中有 个种族,种族的编号分别从
到
,分别生活在编号为
到
的聚居地上,种族的编号与其聚居地的编号相同。有的聚居地之间有双向的道路相连,道路的长度为
。保证连接的方式会形成一棵树结构,即所有的聚居地之间可以互相到达,并且不会出现环。定义两个聚居地之间的距离为连接他们的道路的长度;例如,若聚居地
和
之间有道路,
和
之间有道路,因为每条道路长度为
而且又不可能出现环,所以
与
之间的距离为
。
出于对公平的考虑,第 年,世界树的国王需要授权
个种族的聚居地为临时议事处。对于某个种族
(
为种族的编号),如果距离该种族最近的临时议事处为
(
为议事处所在聚居地的编号),则种族
将接受
议事处的管辖(如果有多个临时议事处到该聚居地的距离一样,则
为其中编号最小的临时议事处)。
现在国王想知道,在 年的时间里,每一年完成授权后,当年每个临时议事处将会管理多少个种族(议事处所在的聚居地也将接受该议事处管理)。 现在这个任务交给了以智慧著称的灵长类的你:程序猿。请帮国王完成这个任务吧。
Input
第一行为一个正整数 ,表示世界树中种族的个数。
接下来 行,每行两个正整数
,
,表示
聚居地与
聚居地之间有一条长度为
的双向道路。
接下来一行为一个正整数 ,表示国王询问的年数。
接下来 块,每块两行:
第 块的第一行为一个正整数
,表示第
年授权的临时议事处的个数。
第 块的第二行为
个正整数
,表示第
年被授权为临时议事处的聚居地编号(保证互不相同)。
Output
输出包含 行,第
行为
个整数,该行的第
个数表示第
年被授权的聚居地
的临时议事处管理的种族个数。
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
对于所有的数据 。
Solution
明确f、ans数组,
表示
通过
这个点能够控制的点的数量
起始值是
是
在虚树上的直接儿子
然后遍历儿子边,找到分界点,
上面是由
控制,下面到
都是由
控制。
这是显然的。
最后
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
#include<bitset>
#define mk make_pair
#define fi first
#define nd second
#define pii pair<int,int>
#define pb push_back
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long ll;
inline ll read() {ll x = 0; char ch = getchar(), w = 1;while(ch < '0' || ch > '9') {if(ch == '-') w = -1;
ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}return x * w;}
void write(ll x) {if(x < 0) putchar('-'), x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0');}
inline void writeln(ll x) {write(x);puts("");}
const int N = 500000;
int head[N], en;
struct Edge {
int u, v, nxt;
}e[N * 2];
int n, m, d[N];
void addedge(int x, int y) {
e[++en].u = x, e[en].v = y, e[en].nxt = head[x], head[x] = en;
}
int dfn[N], num, siz[N];
int f[N][21];
void dfs(int x, int F) {
dfn[x] = ++num;
d[x] = d[F] + 1;
f[x][0] = F;
siz[x] = 1;
for(int i = 1; i <= 20; ++i) f[x][i] = f[f[x][i - 1]][i - 1];
for(int i = head[x]; i;i = e[i].nxt) {
int y = e[i].v;
if(y == F) continue;
dfs(y, x);
siz[x] += siz[y];
}
}
int lca(int x, int y) {
if(d[x] < d[y]) swap(x, y);
for(int i = 20; ~i; --i) if(d[f[x][i]] >= d[y]) x = f[x][i];
if(x == y) return x;
for(int i = 20; ~i; --i) if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return f[x][0];
}
int getdis(int x, int y) {
if(x == 0 || y == 0) return 1e9;
int z = lca(x, y);
return d[x] + d[y] - 2 * d[z];
}
int get(int x, int w) {
for(int i = 0; i <= 20; ++i) if(w & (1 << i)) x = f[x][i];
return x;
}
int t;
struct Que {
int x, i;
bool operator < (const Que &rhs) const {
return dfn[x] < dfn[rhs.x];
}
}a[N];
bool v[N];
struct GGG {
int head[N], en;
struct Edge {
int u, v, nxt;
}e[N * 2];
int n, m;
void addedge(int x, int y) {
e[++en].u = x, e[en].v = y, e[en].nxt = head[x], head[x] = en;
}
int top, st[N];
int f[N], ans[N], bel[N];
void init() {
st[top = 1] = 1;
for(int i = 1; i <= en; ++i) head[e[i].u] = 0;
for(int i = 1; i <= en; ++i) {
bel[e[i].u] = bel[e[i].v] = 0;
f[e[i].u] = f[e[i].v] = 0;
ans[e[i].u] = ans[e[i].v] = 0;
}
en = 0;
}
void ins(int x) {
int p = lca(st[top], x);
while(top > 1 && d[st[top - 1]] >= d[p]) addedge(st[top - 1], st[top]), --top;
if(st[top] == p) {
st[++top] = x;
return;
}
addedge(p, st[top]);
st[top] = p;
st[++top] = x;
}
void dfs(int x, int F) {
if(v[x]) bel[x] = x;
else bel[x] = bel[F];
f[x] = siz[x];
int val1, val2;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].v;
dfs(y, x);
f[x] -= siz[y];
val1 = getdis(bel[y], x);
val2 = getdis(bel[x], x);
if(val1 < val2 || val1 == val2 && bel[y] < bel[x]) bel[x] = bel[y];
}
}
void dfs2(int x, int F) {
int val1 = getdis(x, bel[x]);
int val2 = getdis(x, bel[F]);
if(val1 > val2 || val1 == val2 && bel[F] < bel[x]) bel[x] = bel[F];
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].v;
dfs2(y, x);
}
}
void solve(int x, int F) {
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].v;
if(y == F) continue;
int r = d[y] - d[x] + 1, l = 0;
while(r - l > 1) {
int mid = (l + r) >> 1;
int t = get(y, mid);
int val1 = getdis(t, bel[x]);
int val2 = getdis(t, bel[y]);
if(val1 > val2 || val1 == val2 && bel[x] > bel[y]) l = mid;
else r = mid;
}
int z = get(y, l);
f[x] -= siz[z] - siz[y];
f[y] += siz[z] - siz[y];
solve(y, x);
}
ans[bel[x]] += f[x];
}
}g;
int ans[N];
int main() {
n = read();
for(int i = 1; i < n; ++i) {
int x = read(), y = read();
addedge(x, y);
addedge(y, x);
}
dfs(1, 1);
int Q = read();
d[0] = 1e7;
for(int T = 1; T <= Q; ++T) {
t = read();
for(int i = 1; i <= t; ++i)
a[i].x = read(), a[i].i = i;
sort(a + 1, a +1 + t);
g.init();
for(int i = 1; i <= t; ++i) v[a[i].x] = 1;
for(int i = (a[1].x == 1 ? 2 : 1); i <= t; ++i) g.ins(a[i].x);
while(g.top > 1) g.addedge(g.st[g.top - 1], g.st[g.top]), g.top--;
g.dfs(1, 0);
g.dfs2(1, 0);
g.solve(1, 0);
for(int i = 1; i <= t; ++i) {
ans[a[i].i] = g.ans[a[i].x];
}
for(int i = 1; i <= t; ++i) printf("%d ", ans[i]);
puts("");
for(int i = 1; i <= t; ++i) v[a[i].x] = 0;
}
return 0;
} 
京公网安备 11010502036488号