点分治(树上<=k的路径的个数)

#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define I 1.0000000
#define INF 20090509
#define fd(i,a,b) for(int i=a,_i=b;i<=_i;i=-~i)
#define bd(i,a,b) for(int i=a,_i=b;i>=_i;i=~-i)
#define Db(a,b,c) cout<<a<<';'<<b<<','<<c<<endl;
using namespace std;

const int N=2e5+509,MOD=998244353;
int n,m,tot,root,sn,ans,cnt;
int head[N],s[N],deep[N],vis[N],f[N],d[N];

struct edge
{
	int to,w,nxt;
}e[N];

namespace quicker
{
	inline int read()
	{
		int num=0; bool flag=1; char c=getchar();
		while(!isdigit(c)){if(c=='-') flag=0;c=getchar();}
		while(isdigit(c)){num=(num<<1)+(num<<3)+(c-'0');c=getchar();}
		return flag?num:-num;
	}
	inline void write(int x)
	{
		if(x<0) putchar('-'),x=-x;
		if(x>9) write(x/10);
		putchar((x%10)^48);
	}
	inline void tie0()
	{
		ios::sync_with_stdio(0);
		cin.tie(0); cout.tie(0);
	}
}

namespace FJ
{

	void add(int a,int b,int c)
	{
		e[++tot].nxt=head[a];
		e[tot].to=b;
		e[tot].w=c;
		head[a]=tot;
	}
	
	void getroot(int x,int fa)
	{
		f[x]=0,s[x]=1;
		for(int i=head[x];i;i=e[i].nxt)
		{
			if(e[i].to!=fa&&!vis[e[i].to])
			{
				getroot(e[i].to,x);
				s[x]+=s[e[i].to];
				f[x]=max(f[x],s[e[i].to]);
			}
		}
		f[x]=max(f[x],sn-s[x]);
		if(f[root]>f[x]) root=x;
	}
	
	void getdeep(int x,int fa)
	{
		d[++cnt]=deep[x];
		for(int i=head[x];i;i=e[i].nxt)
		{
			if(e[i].to!=fa&&!vis[e[i].to])
			{
				deep[e[i].to]=deep[x]+e[i].w;
				getdeep(e[i].to,x);
			}
		}
	}
	
	int calc(int x,int w)
	{
		cnt=0;
		deep[x]=w;
		getdeep(x,0);
		sort(d+1,d+cnt+1);
		int l=1,r=cnt,sum=0;
		while(l<=r)
		{
			if(d[l]+d[r]<=m) sum+=r-l,l=-~l;
			else r=~-r;
		}
		return sum;
	}
	
	void dfs(int x)
	{
		vis[x]=1,ans+=calc(x,0);
		for(int i=head[x];i;i=e[i].nxt)
		{
			if(!vis[e[i].to])
			{
				ans-=calc(e[i].to,e[i].w);
				sn=s[e[i].to];
				f[0]=n;
				root=0;
				getroot(e[i].to,0);
				dfs(root);
			}
		}
	}
	
}

using namespace quicker;
using namespace FJ;

signed main()
{
	#ifdef FJ
//	freopen("maxnumber.in","r",stdin);
//	freopen("maxnumber.out","w",stdout);
//	quicker::tie0();
	#endif
	n=read();
	int x,y,z;
	fd(i,1,n-1)
	{
		x=read(),y=read(),z=read();
		add(x,y,z);
		add(y,x,z);
	}
	m=read();
	f[0]=sn=n;
	getroot(1,0);
//	cout<<root<<endl;
	dfs(root);
	write(ans);
	puts("");
	return 0;
}
posted @   whrwlx  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示