[模板]点分治

算法流程:找到树的重心,删去这个点,递归子树。
题号luogu3806

#include <iostream>
#include <ctime>
#include <algorithm>
#include <windows.h>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=10005;
inline int read(){
    int k=0,f=1; char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    return k*f;
}
int n,m,K,siz[N],head[N],ecnt,size,rt,cnt,a[150],f[N];
struct Edge{int to,nxt,val;}e[N<<1];
struct Node{int from,val; bool operator < (const Node &rhs) const {return val<rhs.val;};};
bool vis[N],ans[106];
Node dis[10005];
void add(int bg,int ed,int val){(++ecnt)[e].to=ed;ecnt[e].val=val;ecnt[e].nxt=bg[head];bg[head]=ecnt;}
int binary(int x) {
	int l=1,r=cnt,ans=0;
	while(l<=r) {
		int mid=l+r>>1;
		if(dis[mid].val<x) l=mid+1;
		else r=mid-1,ans=mid;
	}
	return ans;
}
void barycenter(int x,int fa) {
	f[x]=0,siz[x]=1;
	for(int i=head[x];i;i=e[i].nxt) {
		int v=e[i].to;
		if(vis[v]||fa==v) continue;
		barycenter(v,x);
		f[x]=max(f[x],siz[v]);
		siz[x]+=siz[v];
	}
	f[x]=max(f[x],size-siz[x]);
	if(f[x]<f[rt]) rt=x;
}
void dfs(int x,int fa,int from,int val) {
	dis[++cnt]={from,val};
	for(int i=head[x];i;i=e[i].nxt) {
		int v=e[i].to;
		if(vis[v]||fa==v) continue;
		dfs(v,x,from,val+e[i].val);
	}
}
void work(int x) {
	cnt=0;
	for(int i=x[head];i;i=i[e].nxt ) {
		int v=i[e].to;
		if(v[vis]) continue;
		dfs(v,x,v,e[i].val);
	}
	(++cnt)[dis]={0,0};
	sort(dis+1,dis+1+cnt);
	for(int i=1;i<=m;i++) {
		if(i[ans]) continue;
		int l=1;
		while(l<cnt&&a[i]>(dis[l].val+dis[cnt].val)) l++;
		while(l<cnt&&!ans[i]) {
			if(a[i]-dis[l].val<dis[l].val) break;
			int pos=binary(a[i]-dis[l].val);
			while(dis[pos].val+dis[l].val==a[i]&&l<=cnt&&dis[pos].from==dis[l].from) pos++;
			if(dis[pos].val+dis[l].val==a[i]) ans[i]=1;
			l++;
		}
	}
}
void solve(int x) {
	vis[x]=1;
	work(x);
	for(int i=head[x];i;i=e[i].nxt) {
		int v=e[i].to;rt=0;
		if(v[vis]) continue;
		siz[rt]=size=siz[v];
		barycenter(v,0);
		solve(rt);
	}
}
int main() {
	int st=clock();
	n=read();m=read();
	for(int i=1,x,y,z;i<n;i++) 	x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
	for(int i=1;i<=m;i++) a[i]=read();
	f[rt]=size=n;
	barycenter(1,0);
	solve(rt);
	for(int i=1;i<=m;i++)puts(ans[i]?"AYE":"NAY");
	int ed=clock();
	Sleep(200);
	cout<<ed-st;
	return 0;
}
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9475605.html