Codeforces Round #359 (Div. 2) D - Kay and Snowflake

D - Kay and Snowflake

题目大意:给你一棵数q个询问,每个询问给你一个顶点编号,要你求以这个点为根的子树的重心是哪个节点。

定义:一棵树的顶点数为n,将重心去掉了以后所有子树的顶点的个数的两倍不会超过n。

性质 1 :树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个距离和,他们的距离和一样。

性质 2 :把两棵树通过某一点相连得到一颗新的树,新的树的重心必然在连接原来两棵树重心的路径上。

性质 3 :一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。

 #include<bits/stdc++.h>
#define fi first
#define se second
#define mk make_pair
#define ll long long
#define pll pair<ll,ll>
#define pii pair<int,int>
#define read(x) scanf("%d",&x)
#define sread(x) scanf("%s",x)
#define dread(x) scanf("%lf",&x)
#define lread(x) scanf("%lld",&x)
using namespace std; const int N=1e6+;
const int M=1e7+;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+; int n,q,sum[N],fa[N],ans[N];
vector<int> edge[N]; int dfs(int u)
{
sum[u]=; ans[u]=u;
for(int v:edge[u])
sum[u]+=dfs(v); for(int v:edge[u])
if(sum[v]*>sum[u])
ans[u]=ans[v]; while((sum[u]-sum[ans[u]])*>sum[u])
ans[u]=fa[ans[u]]; return sum[u];
} int main()
{
read(n); read(q);
for(int i=;i<=n;i++)
{
int pre; read(pre);
edge[pre].push_back(i);
fa[i]=pre;
}
dfs();
while(q--)
{
int u; read(u);
printf("%d\n",ans[u]);
}
return ;
}
/* */
上一篇:AOJ DSL_2_A Range Minimum Query (RMQ)


下一篇:TMsgThread, TCommThread -- 在delphi线程中实现消息循环