点分治
就是这道题,本想着双倍经验的,然而BZOJ被卡了。。。就换抄了另一种方法。
本来我在统计的时候是平方枚举然后加入桶里的,然后 O(1) O ( 1 ) 回答。这种方法是先离线,再把深度排一遍序,然后二分判断另一个是否存在。把平方变成了一个 log l o g 。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10005
#define inf 1000000
using namespace std;
struct edge{
int next,to,dis;
}ed[N<<1];
int n,k,m,p,t,rt,ans[N],h[N],dis[N];
int dep[N],mx[N],sz[N],q[N];
bool f[N];
inline char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
inline int _read(){
int x=0; char ch=readc();
while (!isdigit(ch)) ch=readc();
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x;
}
#define addedge(x,y,z) ed[++k]=(edge){h[(x)],(y),(z)},h[(x)]=k
void dfsrt(int x,int fa){
sz[x]=1,mx[x]=0;
for (int i=h[x],v;i;i=ed[i].next)
if ((v=ed[i].to)!=fa&&!f[ed[i].to])
dfsrt(v,x),sz[x]+=sz[v],mx[x]=max(mx[x],sz[v]);
mx[x]=max(mx[x],t-sz[x]); if (mx[x]<mx[rt]) rt=x;
}
void dfsdep(int x,int fa){
dep[++p]=dis[x];
for (int i=h[x];i;i=ed[i].next)
if (ed[i].to!=fa&&!f[ed[i].to]){
dis[ed[i].to]=dis[x]+ed[i].dis;
dfsdep(ed[i].to,x);
}
}
int pd(int L,int R,int k){//二分
int ans1=0,ans2=-1,l=L,r=R,mid;
while (l<=r)
if (dep[mid=l+r>>1]==k) ans1=mid,r=mid-1;
else dep[mid]<k?l=mid+1:r=mid-1;
l=L,r=R;
while (l<=r)
if (dep[mid=l+r>>1]==k) ans2=mid,l=mid+1;
else dep[mid]<k?l=mid+1:r=mid-1;
return ans2-ans1+1;
}
int dfssum(int x,int v,int k){
dis[x]=v,p=0,dfsdep(x,0);
sort(dep+1,dep+p+1); int ret=0;
for (int i=1;i<=p;i++){
if ((dep[i]<<1)>k) break;
ret+=pd(i,p,k-dep[i]);
}
return ret;
}
void dfsans(int x){
f[x]=true;
for (int i=1;i<=m;i++) ans[i]+=dfssum(x,0,q[i]);
for (int i=h[x],v;i;i=ed[i].next)
if (!f[v=ed[i].to]){
for (int j=1;j<=m;j++)
ans[j]-=dfssum(v,ed[i].dis,q[j]);
rt=0,t=sz[v],dfsrt(v,0),dfsans(rt);
}
}
int main(){
n=_read(),m=_read();
for (int i=1;i<n;i++){
int u=_read(),v=_read(),d=_read();
addedge(u,v,d);addedge(v,u,d);
}
for (int i=1;i<=m;i++) q[i]=_read();
t=n,mx[0]=0x7fffffff,dfsrt(1,0),dfsans(rt);
for (int i=1;i<=m;i++) puts(ans[i]?"Yes":"No");
return 0;
}