既然已经说了是模板,那么考虑怎么套用点分治。
容易想到记录到所有值的方案数,但是发现瓶颈在于每次结束以后去枚举答案。
因为k在1kw,显然单次统计都会有1kw的复杂度,考虑优化,发现实际上只有不到1w个取值,
那么在每次新增一个取值的时候去更新即可,然后现在又有一个问题在于每次新查找的时候数组的清空。
这个直接套个时间戳即可
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x ;i <= y ; ++ i)
#define repd(i,x,y) for(register int i = x ; i >= y ; -- i)
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
x = 0;char c;int sign = 1;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int N = 1e4 + 50;
int head[N],nxt[N<<1],to[N<<1],w[N<<1],tot;
map<int,int> mp;
int n,m;
inline void add(int x,int y,int val)
{
to[tot] = y;
w[tot] = val;
nxt[tot] = head[x];
head[x] = tot++;
}
int rt,nsum,mx[N],size[N];
bool vis[N];
void get_rt(int x,int fa)
{
size[x] = mx[x] = 1;
for(register int i = head[x];~i;i=nxt[i])
if(!vis[to[i]] && to[i] != fa){
get_rt(to[i],x);
size[x] += size[to[i]];
mx[x] = max(mx[x],size[to[i]]);
}
mx[x] = max(mx[x],nsum - size[x]);
if(mx[x] < mx[rt]) rt = x;
}
int k[101],ans[101];
int op,now,is[10100000];
void dfs(int x,int fa,int val)
{
rep(i,1,m) if(k[i] - val >= 0 && is[k[i]-val] == now) ans[i] += op * mp[k[i] - val];
if(is[val] != now) mp[val] = 1,is[val] = now;else ++ mp[val];
for(register int i = head[x];~i;i=nxt[i])
if(!vis[to[i]] && to[i] != fa)
{
dfs(to[i],x,val + w[i]);
}
}
inline void calc(int x,int w)
{
++now;
dfs(x,x,w);
}
void solve(int x)
{
op = 1;
vis[x] = 1;
calc(x,0);
for(register int i = head[x];~i;i = nxt[i])
if(!vis[to[i]])
{
op = -1;
calc(to[i],w[i]);
rt = 0;nsum = size[to[i]];
get_rt(to[i],to[i]);
solve(rt);
}
}
int main()
{
memset(head,-1,sizeof head);
mx[0] = N;
read(n); read(m);
rep(i,2,n)
{
int u,v,w;
read(u); read(v); read(w);
add(u,v,w); add(v,u,w);
}
rep(i,1,m) read(k[i]);
nsum = n;
get_rt(1,1); solve(rt);
rep(i,1,m) puts(ans[i]?"AYE":"NAY");
return 0;
}