今天发现之前我的点分治板子一直有点问题.把重心提出来之后他剩下每个子树的size正常应该重新求一遍,我还是直接用的求重心的时候的size。这种找法会导致一个子树size求错
理论上来讲复杂度应该会出现问题,但我这个板子从来没有被卡过。
请问是数据过水,还是这种做法本来复杂度就不会退化太多?
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
#define FOR(i,a,b) for(int i = a; i <= b; ++i)
#define _FOR(i,a,b) for(int i = a; i >= b; --i)
#define gjm(i,x) for(int i = head[x]; i; i = e[i].next)
template<typename T>void read(T &x)
{
x = 0;int f = 1;
char c = getchar();
for(;!isdigit(c);c = getchar()) if(c == '-') f = -1;
for(;isdigit(c);c = getchar()) x = x * 10 + c - '0';
x *= f;
}
struct edge
{
int to,next,val;
} e[N << 1];
bool vis[N];
int n,K,rt,min_size,sum;
int head[N],qaq[N],cnt,size[N],dis[N],ans;
void add(int x,int y,int z)
{
e[++cnt] = (edge){y,head[x],z};
head[x] = cnt;
}
void getrt(int x,int fa)
{
int tmp = 0;
size[x] = 1;
gjm(i,x)
{
int y = e[i].to;
if(y == fa || vis[y]) continue;
getrt(y,x);
size[x] += size[y],tmp = max(tmp,size[y]);
}
tmp = max(tmp,sum - size[x]);
if(tmp < min_size) min_size = tmp,rt = x;
}
void getdis(int x,int fa)
{
qaq[++qaq[0]] = dis[x];
gjm(i,x)
{
int y = e[i].to;
if(y == fa || vis[y]) continue;
dis[y] = dis[x] + e[i].val;
getdis(y,x);
}
}
int jisuan(int x,int val)
{
dis[x] = val,qaq[0] = 0;getdis(x,0);
sort(qaq + 1,qaq + qaq[0] + 1);
int l = 1,r = qaq[0],anss = 0;
while(l <= r)
{
if(qaq[l] + qaq[r] <= K) anss += r - l,++l;
else --r;
}
l = 1,r = qaq[0];
while(l <= r)
{
if(qaq[l] + qaq[r] < K) anss -= r - l,++l;
else --r;
}
return anss;
}
void dfs(int x)
{
vis[x] = 1;ans += jisuan(x,0);
gjm(i,x)
{
int y = e[i].to;
if(vis[y]) continue;
ans -= jisuan(y,e[i].val);
sum = size[y],min_size = INT_MAX;
getrt(y,x),dfs(rt);
}
}
int main()
{
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
int m;
read(n),read(m);
FOR(i,1,n - 1)
{
int x,y,z;
read(x),read(y),read(z);
add(x,y,z),add(y,x,z);
}
while(m--)
{
memset(vis,0,sizeof(vis));
ans = 0,read(K);
sum = n,min_size = INT_MAX,getrt(1,0);
dfs(rt);
if(ans == 0) puts("NAY");
else puts("AYE");
}
return 0;
}