【点分治】【点分治序】BZOJ3784 树上的路径

该博客分析了点分治序的概念,即每次找到树的重心后,以重心为根构建DFS序。点分治序长度为NlogN级别。通过分析,当以X为重心时,可以确定所有子树中与X距离的路径,并利用RMQ寻找最长路径。答案可以通过堆来维护,从而求得次长路径。
摘要由CSDN通过智能技术生成

分析:

首先,定义点分治序为:
每次找到重心后,以重心为根,当前子树的DFS序。每一个重心的DFN序次连接,就组成了点分治序。显然,点分治序的长度是 N l o g N Nlog N NlogN级的。

现在,根据一般点分治的方式,在以X为重心时,我们要找到所有子树中的点,与X的距离。对某个点u而言,如果考虑u->x->v的一条路径,则v不能在与u相同的子树中。且这个v在点分治序上的位置是相邻的。
在这里插入图片描述
于是,就可以找到对任意一个点u,经过某个重心,到达另一部分的点的最长路径。

找到全局最长路径后,显然这条路径可以加入答案。现在考虑次大的路径:把最长路径拆分为两部分,其余不变。
在这里插入图片描述

找最大值用RMQ即可。答案可以用堆来维护,弹出M次即可。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>
#define SF scanf
#define PF printf
#define MAXN 50010
using namespace std;
vector<int> a[MAXN],w[MAXN];
int n,m,cnt,tot;
int dist[MAXN*20];
int siz[MAXN],maxsiz[MAXN];
struct node{
   
	int l,r,dis,ans,pos;
	bool operator <(const node &a) const {
   
		if(ans!=a.ans)
			return ans<a.ans;
		if(dis!=a.dis)
			return dis<a.dis;
		if(l!=a.l)
			return l<a.l;
		return r<a.r;
	}
}que[MAXN*40];
priority_queue<node> q;
bool used[MAXN];
int find_g(int x,int fa,int siz1){
   
	siz[x]=1;
	maxsiz[x]=0;
	int g=-1;
	for(int i=0;i<int(a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值