題目描述
Description
給出一棵帶邊權的樹,問有多少對點的距離<=Len
Input
第一行兩個整數N,Len(2<=n<=10000,len<=maxlongint)
接下來N-1行,每行3個整數,x,y,l,表示x和y有一條邊長爲l的邊
Output
一行,一個整數ans,表示答案
Sample Input
5 4
1 2 3
1 3 1
1 4 2
3 5 1
Sample Output
8
題解
點分治
沒什麼好說的
每次求經過重心的路徑,線段樹維護
建樹時要求父親及以上的子樹的size,向下走時維護最大和次大的size
其實早就學了只是一直沒打
好像寫成維護深度了其實直接用總size-子樹size即可
code
#include <iostream>
#include <cstdlib>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std;
int tr[320001][3];
int a[20001][3];
int ls[10001];
int f[10001];
bool bz[10001];
int n,Len,i,j,k,l,len,ans,Find,tlen,fmin,fMin;
long long LEN;
void clear(int t)
{
tr[t][0]=0;
tr[t][1]=0;
tr[t][2]=0;
}
void tNew(int t,int x)
{
if (!tr[t][x])
{
tr[t][x]=++tlen;
clear(tlen);
}
}
void tchange(int t,long long l,long long r,int x)
{
long long mid=(l+r)/2;
++tr[t][2];
if (l==r)
return;
if (x<=mid)
{
tNew(t,0);
tchange(tr[t][0],l,mid,x);
}
else
{
tNew(t,1);
tchange(tr[t][1],mid+1,r,x);
}
}
void tfind(int t,long long l,long long r,int x,int y)
{
long long mid=(l+r)/2;
if (x<=l && r<=y)
{
Find+=tr[t][2];
return;
}
if (x<=mid && tr[t][0])
tfind(tr[t][0],l,mid,x,y);
if (mid<y && tr[t][1])
tfind(tr[t][1],mid+1,r,x,y);
}
void New(int x,int y,int z)
{
++len;
a[len][0]=y;
a[len][1]=ls[x];
ls[x]=len;
a[len][2]=z;
}
void dfs(int fa,int t)
{
int i;
f[t]=1;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=fa && !bz[a[i][0]])
{
dfs(t,a[i][0]);
f[t]=max(f[t],f[a[i][0]]+1);
}
}
void dfs2(int fa,int t,int s)
{
int i,max1=0,Max1=-1,max2=0,Max2=-1;
if (max(s,f[t]-1)<fmin)
{
fmin=max(s,f[t]-1);
fMin=t;
}
if (!ls[t])
return;
++s;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=fa && !bz[a[i][0]])
{
if (f[a[i][0]]+1>max1)
{
max2=max1;
Max2=Max1;
max1=f[a[i][0]]+1;
Max1=a[i][0];
}
else
if (f[a[i][0]]+1>max2)
{
max2=f[a[i][0]]+1;
Max2=a[i][0];
}
}
if (Max2>-1)
{
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=fa && !bz[a[i][0]])
{
if (a[i][0]==Max1)
dfs2(t,a[i][0],max(s,max2));
else
dfs2(t,a[i][0],max(s,max1));
}
}
else
{
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=fa && !bz[a[i][0]])
dfs2(t,a[i][0],s);
}
}
void dfs_clear(int fa,int t)
{
int i;
f[t]=0;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=fa && !bz[a[i][0]])
dfs_clear(t,a[i][0]);
}
int find_zx(int t)
{
dfs(0,t);
fmin=233333333;
dfs2(0,t,0);
dfs_clear(0,t);
return fMin;
}
void dfs3(int fa,int t,int s)
{
int i;
Find=0;
tfind(1,1,Len,1,Len-s);
ans+=Find+1;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=fa && !bz[a[i][0]] && s<=Len-a[i][2])
dfs3(t,a[i][0],s+a[i][2]);
}
void dfs4(int fa,int t,int s)
{
int i;
tchange(1,1,Len,s);
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=fa && !bz[a[i][0]] && s<=Len-a[i][2])
dfs4(t,a[i][0],s+a[i][2]);
}
void work(int t)
{
int i,zx=find_zx(t);
t=zx;
bz[t]=1;
tlen=1;
clear(1);
for (i=ls[t]; i; i=a[i][1])
if (!bz[a[i][0]])
{
dfs3(t,a[i][0],a[i][2]);
if (a[i][1])
dfs4(t,a[i][0],a[i][2]);
}
for (i=ls[t]; i; i=a[i][1])
if (!bz[a[i][0]])
work(a[i][0]);
}
int main()
{
// freopen("data1.in","r",stdin);
// freopen("1166.in","r",stdin);
scanf("%d%d",&n,&Len);
fo(i,1,n-1)
{
scanf("%d%d%lld",&j,&k,&LEN);
if (LEN<=Len)
{
l=LEN;
New(j,k,l);
New(k,j,l);
}
}
fo(i,1,n)
if (!bz[i])
work(i);
printf("%d\n",ans);
}