题目:
题意:
点分治!!!
分析:
点分治
.
.
..
..
滚,虽然也没有可以讲的扣就完事了理解好就行
这里讲一下自己计算答案时的一个部分,我们设
t
t
i
tt_i
tti表示到当前重心的距离为
i
i
i的路径是否存在
对于每个询问
q
i
q_i
qi,因为我们便利完前面的
i
−
1
i-1
i−1棵子树,所以用
t
t
q
i
−
i
tt_{q_i-i}
ttqi−i来判断在之前的子树中,有没有能与当前这个距离为
i
i
i的路径拼出长度为
q
i
q_i
qi的路径,如果有,那么答案就是
A
Y
E
AYE
AYE,否则就是
N
A
Y
NAY
NAY
代码:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define LL long long
#define LZX WCIMU
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
struct node{
LL to,next,w;
}e[20005];
LL ls[20005],cnt=0,n=read(),m=read();
void add(LL x,LL y,LL w)
{
e[cnt]=(node){y,ls[x],w};
ls[x]=cnt++;
return;
}
LL qu[105],maxp[10005],size[10005],sum,tf[10005],root=0;
void find(LL u,LL fa)
{
size[u]=1;maxp[u]=0;
for(LL i=ls[u];~i;i=e[i].next)
{
LL v=e[i].to;
if(v==fa||tf[v]) continue;
find(v,u);
size[u]+=size[v];
maxp[u]=max(maxp[u],size[v]);
}
if(maxp[u]<maxp[root]) root=u;
return;
}
LL dis[10005],l1,l2,tt[10000005],rem[10005],bc[10005],ff[105];
void get(LL u,LL fa)
{
rem[++l1]=dis[u];
for(LL i=ls[u];~i;i=e[i].next)
{
LL v=e[i].to;
if(v==fa||tf[v]) continue;
dis[v]=dis[u]+e[i].w;
get(v,u);
}
return;
}
void calc(LL u)
{
l2=0;
for(LL i=ls[u];~i;i=e[i].next)
{
LL v=e[i].to;
if(tf[v]) continue;
l1=0;dis[v]=e[i].w;
get(v,u);
for(LL j=l1;j;j--)
for(LL k=1;k<=m;k++)
if(qu[k]>=rem[j]) ff[k]|=tt[qu[k]-rem[j]];
for(LL j=1;j<=l1;j++) bc[++l2]=rem[j],tt[rem[j]]=1;
}
for(LL i=1;i<=l2;i++) tt[bc[i]]=0;
return;
}
void work(LL u)
{
tf[u]=tt[0]=1;
calc(u);
for(LL i=ls[u];~i;i=e[i].next)
{
LL v=e[i].to;
if(tf[v]) continue;
sum=size[v];maxp[root=0]=23333333;
find(v,0);work(v);
}
return;
}
int main()
{
memset(ls,-1,sizeof(ls));
for(LL i=1;i<n;i++)
{
LL x=read(),y=read(),w=read();
add(x,y,w);add(y,x,w);
}
for(LL i=1;i<=m;i++) qu[i]=read();
maxp[0]=sum=n;
find(1,0);
work(root);
for(LL i=1;i<=m;i++) if(ff[i]) printf("AYE\n"); else printf("NAY\n");
return 0;
}