背景:
好久没看。忘记了。
题目传送门:
https://www.luogu.org/problemnew/show/P3806
思路:
点分治模板。
留下一个模板。
好像时间复杂度是
Θ
(
n
2
)
\Theta(n^2)
Θ(n2)的,因为
s
o
l
v
e
solve
solve函数是两重循环。
l
u
o
g
u
luogu
luogu的题解大多也是平方级别的,少数几篇才是
l
o
g
2
log^2
log2级别的。所以你们不要看我的,水个访问量就走,代码还是可以看的。
那又怎么样,数据水。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,len=0;
int last[200010],size[200010],msize[200010],dis[200010],sum[200010];
bool bz[200010];
struct node{int x,y,z,next;} a[200010];
int SIZE,MIN,ROOT,tot;
void ins(int x,int y,int z)
{
a[++len]=(node){x,y,z,last[x]}; last[x]=len;
}
void find_root(int x,int fa)
{
size[x]=1;
msize[x]=0;
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa||bz[y]) continue;
find_root(y,x);
size[x]+=size[y];
msize[x]=max(msize[x],size[y]);
}
msize[x]=max(msize[x],SIZE-size[x]);
if(MIN>msize[x]) MIN=msize[x],ROOT=x;
}
void get_dis(int x,int fa,int z)
{
dis[++tot]=z;
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(bz[y]||y==fa) continue;
get_dis(y,x,z+a[i].z);
}
}
void solve(int x,int z,int op)
{
tot=0;
get_dis(x,0,z);
for(int i=1;i<=tot;i++)
for(int j=i+1;j<=tot;j++)
sum[dis[i]+dis[j]]+=op;
}
void dfs(int x)
{
bz[x]=true;
solve(x,0,1);
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(bz[y]) continue;
solve(y,a[i].z,-1);
SIZE=size[y],MIN=SIZE,ROOT=0;
find_root(y,0);
dfs(ROOT);
}
}
int main()
{
int x,y,z;
scanf("%d %d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d %d %d",&x,&y,&z);
ins(x,y,z),ins(y,x,z);
}
SIZE=n,MIN=n,ROOT=0;
find_root(1,0);
dfs(ROOT);
for(int i=1;i<=m;i++)
{
scanf("%d",&x);
printf(sum[x]?"AYE\n":"NAY\n");
}
}