点分治学习笔记

严肃重新学习。

可以解决树上的路径问题。例如求树上某类满足条件的路径的最值、条件。

设根为 \(p\),因为是路径显然我们可以选择任意一个点作为根。

将树上的路径分为经过 \(p\) 和不经过 \(p\)

点分治即对于一个 \(p\),遍历其子树的所有信息,然后将经过 \(p\) 的路径的贡献计算上,然后将 \(p\) 删掉,对其子树分别分治求解的过程。

分析一下复杂度。设递归层数为 \(h\),复杂度为 \(O(hn)\)

如果我们不断将重心设为根,则递归层数最多 \(\log\),复杂度为 \(O(n\log n)\)

算法流程大概就是以重心为根进行遍历顺便求出子树大小和其儿子子树的重心,计算答案,标记这个根已被删除,递归儿子。

点分治 1

写的非常丑。

#include<bits/stdc++.h>
#define sd std::
//#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define ff(i,a,b) for(int i=(a);i>=(b);i--)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define dbg(x) sd cout<<#x<<":"<<x<<" "
#define dg(x) sd cout<<#x<<":"<<x<<"\n"
#define inf 1e10
int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
void put(int x){print(x);putchar('\n');}
void printk(int x){print(x);putchar(' ');}
const int N=1e4+10,P=1e9+7,V=1e7;
int n,m,siz[N],f[N],da[N],dep[N],vis[N],t[V+10],pos[V+10];//vis[i]为i是否被删掉
sd vector<pii> G[N];
int dis[N],c;
void dfs1(int u,int fa,int d,int las)//求出以 u 为根的重心以及其他信息,并贡献
{
	
	// printk(u),printk(fa),put(d);
	if(d<=V)
	{
		// dg(d);
		if(!t[d]) dis[++c]=d,t[d]++,pos[d]=las;
		else if(pos[d]!=las) t[d]++,pos[d]=las;
	}
	siz[u]=1;f[u]=u;
	dep[u]=dep[fa]+1;
	da[u]=fa;
	for(auto [v,w]:G[u])
	{
		if(v==fa||vis[v]) continue;
		dfs1(v,u,d+w,las?las:v);
		siz[u]+=siz[v];
	}
	for(auto [v,w]:G[u])
	{
		if(v==fa||vis[v]) continue;
		int x=f[v];
		while(siz[x]<(siz[u]+1)/2) x=da[x];
		if(dep[f[u]]<dep[x]) f[u]=x;
	}
}
void dfs3(int u,int fa,int d)//删除这个子树的影响
{
	if(d<=V) t[d]=pos[d]=0;
	for(auto [v,w]:G[u])
	{
		if(v==fa||vis[v]) continue;
		dfs3(v,u,d+w);
	}
}
int K[N],ans[N];
void dfs2(int u,int fa)//以u为根计算答案
{
	// dg(u);
	c=0;
	dfs1(u,fa,0,0);
	// dg(c);
	// F(i,1,c) printk(dis[i]);
	// puts("");
	F(i,1,c) F(j,1,m)
	{
		ans[j]|=(K[j]==dis[i]);
		if(K[j]<dis[i]||!t[K[j]-dis[i]]) continue;
		if(dis[i]==K[j]-dis[i]) ans[j]|=t[dis[i]]>1;
		else ans[j]|=(t[dis[i]]>1||t[K[j]-dis[i]]>1),ans[j]|=(pos[dis[i]]!=pos[K[j]-dis[i]]);
	}
	dfs3(u,fa,0);
	vis[u]=1;
	for(auto [v,w]:G[u])
	{
		if(v==fa||vis[v]) continue;
		dfs2(f[v],0);
	}
}
void solve()
{
	n=read(),m=read();
	F(i,2,n)
	{
		int x=read(),y=read(),z=read();
		G[x].emplace_back(y,z);
		G[y].emplace_back(x,z);
	}
	F(i,1,m) K[i]=read();
	dfs1(1,0,0,0);
	// put(f[1]);
	dfs3(1,0,0);
	dfs2(f[1],0);
	F(i,1,m) puts(ans[i]?"AYE":"NAY");
}
int main()
{
// 	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int T=1;
	// T=read();
	while(T--) solve();
    return 0;
}
posted @ 2025-10-15 17:16  _E_M_T  阅读(5)  评论(0)    收藏  举报