首页 > 其他分享 >点分治学习笔记

点分治学习笔记

时间:2024-07-14 11:29:43浏览次数:8  
标签:ch int 分治 笔记 学习 子树 mx size

分治就是将一个问题划分成多个子问题来求解。
点分治就是在树上进行分治,一般是来统计路径信息的。
对于以 \(u\) 为根的子树内,所有的路径可以划分为两类,一类跨越了子树,经过了 \(u\),另一类没有跨越,只经过子树中的点,而子树内的点又可以再分类,这就是点分治。
为了保证时间复杂度,每次需要选择子树中的重心来统计,保证了点分治的时间复杂度为 \(\mathcal{O}(n\log n)\)。

inline void findrt(int x,int fa,int cnt){
	size[x]=1;int mx=0;
	for(int i=head[x],y;i;i=e[i].next){
		if(vis[y=e[i].v]||y==fa)continue;
		findrt(y,x,cnt);
		size[x]+=size[y];
		mx=std::max(size[y],mx);
	}
	mx=std::max(mx,cnt-size[x]);
	if(mx<=cnt/2)rt=x;
}

找根一次要找两遍,一遍找根,一遍统计正确的子树信息。

点分治有两种写法,一种是容斥统计,一种是分子树统计。
首先简单介绍一下容斥的写法
```cpp
inline void solve(int x){
	vis[x]=1;ans+=calc(x,0);
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].v;
		if(vis[v])continue;
		ans-=calc(x,dis[x]);
	}
	mp.clear();
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].v;
		if(vis[v])continue;
		findrt(v,0,size[v]);
		findrt(rt,0,size[v]);
		solve(rt);
	}
}

在第一次计算完根的贡献后,有一些贡献是不合法的(同一子树内结合),所以需要减去子树内在根的参数下的贡献。
分子树就是每遍历完一颗子树后计算它提供的贡献,计算完后在更新它的信息,这样保证了所有的贡献都是跨越子树的,每找完一个根后清空一下信息。

P3806 【模板】点分治 1

给定一棵有 \(n\) 个点的树,询问树上距离为 \(k\) 的点对是否存在。
拿 map 记一下到根的 \(dis\) 距离是否出现,然后直接分子树统计即可。

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
const int N=1e4+10;
int cmax,n,m,head[N],tot,rt,size[N],t,ans[N],q[N],dep[N],dis[N];
bool vis[N];
std::unordered_map<int,int> mp;
struct EDGE{int v,next,w;}e[N<<1];
inline void add(int u,int v,int w){e[++tot]={v,head[u],w},head[u]=tot;}
inline void findrt(int x,int fa,int cnt){
	size[x]=1;int mx=0;
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].v;
		if(v==fa||vis[v])continue;
		findrt(v,x,cnt);
		size[x]+=size[v];
		mx=std::max(mx,size[v]);
	}
	mx=std::max(mx,cnt-size[x]);
	if(mx<cmax)rt=x,cmax=mx;
}
inline void clac(int x,int fa){
	dep[++t]=x;
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].v;
		if(vis[v]||v==fa)continue;
		dis[v]=dis[x]+e[i].w;
		clac(v,x);
	}
}
inline void solve(int x){
	vis[x]=mp[0]=1;
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].v;
		if(vis[v])continue;
		dis[v]=e[i].w;
		clac(v,x);
		for(int j=1;j<=m;++j)
			for(int k=1;k<=t;++k)
				if(mp.count(q[j]-dis[dep[k]]))ans[j]=1;
		for(int j=1;j<=t;++j)mp[dis[dep[j]]]=1;
		t=0;
	}
	mp.clear();
	for(int i=head[x];i;i=e[i].next){
		int v=e[i].v;
		if(vis[v])continue;
		cmax=1e9;findrt(v,0,size[v]);
		findrt(rt,0,size[v]);
		solve(rt);
	}
}
signed main(){
	// freopen("in.in","r",stdin);freopen("out.out","w",stdout);
	std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
	n=read();m=read();
	for(int i=1;i<n;++i){
		int u=read(),v=read(),w=read();
		add(u,v,w),add(v,u,w);
	}
	for(int i=1;i<=m;++i)q[i]=read();
	cmax=1e9;findrt(1,0,n);findrt(rt,0,n);
	solve(rt);
	for(int i=1;i<=m;++i)std::cout<<(ans[i]?"AYE\n":"NAY\n");
}

标签:ch,int,分治,笔记,学习,子树,mx,size
From: https://www.cnblogs.com/Ishar-zdl/p/18301284

相关文章

  • 【深度学习入门篇 ⑤ 】PyTorch网络模型创建
    【......
  • 从零入门NLP竞赛Task1学习记录
    一、魔搭平台操作流程首先,通过阅读文档,我按照相应步骤进入了魔搭平台,并在GPU环境下上传了数据和代码文件。在成功运行并跑通baseline后,我发现下载的压缩包和对应代码文件的具体用途目前还不甚明了,但我相信通过后续的学习,我会逐渐理解它们的作用。在等待过程中,我顺便了解了机器......
  • 机器学习方法(MATLAB)
    机器学习是一类算法的总称,利用历史数据对机器进行训练,而学习到某种方法或模式,并建立预测未来结果的模型。机器学习分为两类学习方法:有监督学习,利用有标识的历史数据进行训练,实现对新数据的标识的预测。主要包括分类和回归。无监督学习,用于在历史数据中发现隐藏的模式或内在结......
  • 【java深入学习第5章】Spring Boot 中统一功能的实现与处理
    SpringBoot统一功能处理在开发Web应用程序时,为了提高代码的可维护性和可扩展性,我们通常会采用一些统一的功能处理方式。本文将介绍如何在SpringBoot中实现统一的数据返回格式、异常处理和功能处理,并通过一个图书管理系统的案例来演示这些功能的实现。一、统一数据返回格......
  • 【java深入学习第6章】Spring事件监听机制详解
    在Spring框架中,事件监听机制是一个强大且灵活的功能,允许我们在应用程序中发布和监听事件。这种机制可以帮助我们实现松耦合的设计,使得不同模块之间的通信更加灵活和可维护。本文将详细介绍Spring的事件监听机制,并通过代码示例展示如何使用这一功能。1.什么是Spring事件监听机制?......
  • 【机器学习】精准农业新纪元:机器学习引领的作物管理革命
    ......
  • 【java深入学习第4章】精通 Java 微服务:Spring Boot 与 Spring Cloud 的核心技术与设
    在现代软件开发中,微服务架构因其灵活性和可扩展性而备受青睐。本文将探讨Java微服务架构中的关键技术和设计原则,并通过SpringBoot和SpringCloud提供代码示例,展示如何构建一个简单的微服务应用。关键技术和设计原则服务拆分:将单体应用拆分为多个独立的微服务,每个服务负责特定......
  • 前端学习-flutter学习-010-按钮
    《Flutter实战·第二版》ElevatedButton(child:Text("ElevatedButton默认带有阴影和灰色背景。按下后,阴影会变大"),onPressed:(){},),TextButton(child:Text("TextButton默认背景透明并不带阴影。按下后,会有背景色"),onPressed:(){},),......
  • 【java深入学习第2章】Spring Boot 结合 Screw:高效生成数据库设计文档之道
    在开发过程中,数据库设计文档是非常重要的,它可以帮助开发者理解数据库结构,方便后续的维护和扩展。手动编写数据库设计文档不仅耗时,而且容易出错。幸运的是,可以使用SpringBoot和Screw来自动生成数据库设计文档。什么是Screw?Screw是一个开源的数据库文档生成工具,它可以根据数据库......
  • 前端学习-flutter学习-009-文本及样式
    《Flutter实战·第二版》TextTextAlign:leftrightcenter注意点:对齐的参考系是Textwidget本身,如果文本不够长,设置看起来是没有生效的;文本长才看得到,字符串内容超过一行,Text宽度等于屏幕宽度,第二行文本便会居中显示。maxLines、overflow:指定文本显示的最大行数,默认情况下,......