模板—算法——动态点分治

模板—算法——动态点分治

Code:

#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100010
int head[N],to[N<<1],val[N<<1],nxt[N<<1];
int mx[N],size[N],n,all,idx,root,fa[N]; bool vis[N];
void add(int a,int b,int c)
	{nxt[++idx]=head[a],to[idx]=b,val[idx]=c,head[a]=idx;}
void getroot(int p,int from)
{
	mx[p]=0,size[p]=1;
	for(int i=head[p];i;i=nxt[i])
		if(to[i]!=from&&(!vis[to[i]])) getroot(to[i],p),
			size[p]+=size[to[i]],mx[p]=max(mx[p],size[to[i]]);
	mx[p]=max(all-size[p],mx[p]);
	if(mx[root]>mx[p]) root=p;
}
void getsize(int p,int from)
{
	size[p]=1;
	for(int i=head[p];i;i=nxt[i]) if(to[i]!=from&&(!vis[to[i]]))
		getsize(to[i],p),size[p]+=size[to[i]];
}
void dfs2(int p)
{
	vis[p]=true,getsize(p,0);
	for(int i=head[p];i;i=nxt[i]) if(!vis[to[i]])
		all=size[to[i]],root=0,getroot(to[i],0),fa[root]=p,dfs2(root);
}
int main()
{
	scanf("%d",&n);
	for(int i=1,x,y,z;i<n;i++)
		scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
	root=0,mx[0]=n+1,all=n,getroot(1,0),dfs2(root);
}

  

原文地址:https://www.cnblogs.com/yangsongyi/p/10658064.html

时间: 2024-10-17 21:55:02

模板—算法——动态点分治的相关文章

点分治+动态点分治

最近好颓废,什么都学不进去... 感谢两篇:AKMer - 浅谈树分治  言简意赅 LadyLex - 点分治&动态点分治小结  讲解+例题,学到很多东西 点分治 动态点分治 ~ 点分治 ~ 经常遇见一类树上的计数题,问的是在某些条件下,选择一些点的方案数 若对于每个点的统计都需要遍历以其为根节点的子树,普通的做法就是$O(n^2)$的,在很多时候是不满足要求的 而这是点分治的专长 点分治是这样进行的: 1. 找到当前树的重心 2. 将重心及重心连出的边全部删去,那么就能将原来的树分割成森林 3

【BZOJ1095】【ZJOI2007】捉迷藏 [动态点分治]

捉迷藏 Time Limit: 40 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏. 他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达. 游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯. 在起初

关于树论【动态点分治】

搬运:题意传送门:http://caioj.cn/problem.php?id=1433 前几天跟波* * * *老师一起搞这题,结果最后莫名其妙的被波老师D飞... 我用到的是动态点分治. 动态点分治就是基于树的重心(一棵树中,以重心为根的最大子树的节点最小)上的解法,该解法将一棵树分成若干棵子树,对每一棵子树进行重新分配,一直往下分直到每一颗树的节点数为1,上一层的重心需要连接下一层的重心,对这棵新树来进行分治递归求解. 这道题的做法: 对于新树每个节点我们用两个堆来维护,每个节点的第一个堆

动态点分治学习笔记

学习动态点分治之前要先弄清楚点分治的原理,二者的应用范围的不同就在于动态的支持在线修改操作,而实现的不同就在于动态点分治要建点分树. OI中有很多树上统计问题,这类问题往往都有一个比较容易实现的暴力做法,而用高级数据结构维护信息有显得过于复杂,有没有一种"优美的暴力",能既保证思维的简单性,又有更高效的时间复杂度保证呢?这就是点分治的思想. 点分治的实现过程是:每次找到当前树的重心,然后以这个重心为根统计这个树的信息,然后对重心的每个孩子分别递归,同样用将重心作为根的方法统计子树的信息

[BZOJ4012][HNOI2015]开店(动态点分治)

4012: [HNOI2015]开店 Time Limit: 70 Sec  Memory Limit: 512 MBSubmit: 2168  Solved: 947[Submit][Status][Discuss] Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面 向什么样的人群.很神奇的是,幻想乡的地

[ZJOI2007]捉迷藏 解题报告 (动态点分治)

[ZJOI2007]捉迷藏 近期做过的码量最大的一题 (当然也是我写丑了....) 题意 有一个 \(n\) 个节点的树 (\(n \le 10^5\)), 每个节点为黑色或白色. 有 \(m\) 个操作 (\(m \le 5 \times 10^5\)), 操作有两种, 将点 \(x\) 的的颜色翻转. 查询树上距离最远的黑色点对之间的距离. 思路 首先, 如果没有修改操作的话, 就是一个裸的点分治 (点分治学习笔记). 有修改操作, 那就 动态点分治. 动态点分治的基本思路是 (个人总结的)

算法基础:分治模式,归并排序ΘΘΘΘΘΘ知识小结

1.分治模式在每层递归时都有三个步骤:分解,解决,合并 2.归并排序算法完全遵循分治模式: 分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列 解决:使用归并排序递归的排序两个子序列 合并:合并两个已排序的子序列以产生已排序的答案 3.分析分治算法所需要的时间计算: 假设T(n)是规模为n的一个问题的运行时间,若问题足够小,如对某个常量c,n≦c,则直接求解需要常量时将,我们将其写作Θ(1).假设吧原问题分解成a个子问题,每个子问题的规模是原问题的1/b(对归并排序,a和b都为2,然

BZOJ 3924: [Zjoi2015]幻想乡战略游戏(动态点分治)

这种动态点分治嘛,GDKOI时听打到了,也有同学讲到了,所以印象比较深刻也就想出来了,然后就在实现方面卡了好久= = 不得不说CLJ说得真的太简单了,实现方面根本没提. 首先我们可以先用树分治构建出这棵树的分治树,也就是把这棵树的重心作为根节点然后子树为他的子树的重心这样递归下去,然后每个节点存的是其子树的信息. 对于每个节点我们保存这个子树的dv的总和已经把该节点作为点的答案值 这样对于修改能在log n的时间内解决 寻找答案的时候,我们可以发现,如果现在节点的子树dv和*2大于总节点,那么向

【从零学习经典算法系列】分治策略实例——二分查找

1.二分查找算法简介 二分查找算法是一种在有序数组中查找某一特定元素的搜索算法.搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束:如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较.如果在某一步骤数组 为空,则代表找不到.这种搜索算法每一次比较都使搜索范围缩小一半.折半搜索每次把搜索区域减少一半,时间复杂度为Ο(logn). 二分查找的优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且