传送门

题意简述:给出一棵树,求每个子树的重心。


首先通过画图可以观察出一个性质,我们从叶子结点向根节点递推重心的话重心的位置是不会下降的。

然后由于一个点的重心要么是自己,要么在重儿子子树内,因此如果重心不是自己,我们从重儿子子树的重心向自己爬统计答案就行了,由于重心不会下降因此时间复杂度O(n)O(n)O(n)

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=3e5+5;
int n,q,siz[N],fa[N],dep[N],hson[N],ans[N];
vector<int>e[N];
void dfs1(int p){
	siz[p]=1;
	for(ri i=0,v;i<e[p].size();++i){
		v=e[p][i];
		fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
		if(siz[v]>siz[hson[p]])hson[p]=v;
	}
}
void dfs2(int p){
	if(!hson[p]){ans[p]=p;return;}
	for(ri i=0;i<e[p].size();++i)dfs2(e[p][i]);
	if(siz[hson[p]]*2<=siz[p])ans[p]=p;
	else for(ri v=ans[hson[p]];v!=p;v=fa[v])if(max(siz[hson[v]],siz[p]-siz[v])*2<=siz[p]){ans[p]=v;break;}
}
int main(){
	n=read(),q=read();
	for(ri i=2;i<=n;++i)e[read()].push_back(i);
	dfs1(1),dfs2(1);
	while(q--)cout<<ans[read()]<<'\n';
	return 0;
}

最新文章

  1. jQuery 2.0.3 源码分析 事件绑定 - bind/live/delegate/on
  2. java动态代理浅析
  3. 使用ECMAscript5中的forEach函数遍历数组
  4. spring security源码分析之web包分析
  5. jquery 验证插件 validate
  6. wordpress博客搬家心得
  7. [C++程序设计]变量的存储类别
  8. 批量自动更新SVN版本库 - Windows
  9. 【转载】目前主流过滤XSS的三种技术
  10. Apple watch ,小米微信通知
  11. Java接口自动化测试之Maven项目的创建(一)
  12. 如何突破Ue4材质编辑器没有Pass的概念
  13. [转java发送http的get、post请求]
  14. Python多线程基本操作
  15. Linux应急响应思路详谈
  16. BZOJ P4720[Noip2016]换教室____solution
  17. c# windows service 程序
  18. centos7安装后的防火墙问题
  19. 推广Facebook技巧
  20. ubuntu 关闭触控板

热门文章

  1. UNITY3D 2D物流流体插件下载|Liquid Physics 2D
  2. JSP跳转到指定位置
  3. RPC 框架之 Goole protobuf
  4. 【 python】输出随机的字符或数字
  5. log4j 产生的日志位置设置和catalina.home、catalina.base
  6. 利用jenkins+saltstack+sh 修改nginx配置文件并重新加载
  7. WorkerMan源码分析(resetStd方法,PHP中STDIN, STDOUT, STDERR的重定向)
  8. [Mysql]——通过例子理解事务的4种隔离级别(转)
  9. Selenium + Python + Firefox
  10. rem初始化