题目:https://www.luogu.org/problemnew/show/P3806
就是点分治~
每次暴力枚举询问即可,复杂度是 nmlogn;
注意 tmp[0]=1 !
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const maxn=10005,maxm=1e7+5,inf=0x3f3f3f3f; int n,m,hd[maxn],ct,to[maxn<<1],nxt[maxn<<1],w[maxn<<1],dis[maxn],siz[maxn]; int mx,rt,sum,q[105],tmp[maxm],sta[maxn],top,f[maxn]; bool vis[maxn],ans[105]; void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;} void getrt(int x,int fa) { siz[x]=1; int nmx=0; for(int i=hd[x],u;i;i=nxt[i]) { if((u=to[i])==fa||vis[u])continue; getrt(u,x); siz[x]+=siz[u]; nmx=max(nmx,siz[u]); } nmx=max(nmx,sum-siz[x]); if(nmx<mx)mx=nmx,rt=x; } void dfs(int x,int fa) { for(int i=hd[x],u;i;i=nxt[i]) { if((u=to[i])==fa||vis[u])continue; dis[u]=dis[x]+w[i]; for(int j=1;j<=m;j++) if(dis[u]<=q[j]&&!ans[j]) { ans[j]=tmp[q[j]-dis[u]]; sta[++top]=dis[u]; } dfs(u,x); } } void work(int x,int ss) { vis[x]=1; int p=1; for(int i=hd[x],u;i;i=nxt[i]) { if(vis[u=to[i]])continue; dis[u]=w[i]; for(int j=1;j<=m;j++) if(dis[u]<=q[j]&&!ans[j]) { ans[j]=tmp[q[j]-dis[u]]; sta[++top]=dis[u]; } dfs(u,x); for(;p<=top;p++)tmp[sta[p]]++; } for(int i=1;i<=top;i++)tmp[sta[i]]--; top=0; for(int i=hd[x],u;i;i=nxt[i]) { if(vis[u=to[i]])continue; sum=(siz[u]>siz[x]?ss-siz[x]:siz[u]); mx=inf; getrt(u,0); work(u,sum); } } int main() { scanf("%d%d",&n,&m); for(int i=1,x,y,z;i<n;i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } for(int i=1;i<=m;i++)scanf("%d",&q[i]); tmp[0]=1;//! sum=n; mx=inf; getrt(1,0); work(rt,sum); for(int i=1;i<=m;i++) if(ans[i])printf("AYE "); else printf("NAY "); return 0; }