淀粉质
主要思想就是每次找一个根使其任意一个子树大小小于\(\frac{size} 2\),处理跨根路径的答案然后删掉这个跟,并对于它的每一个子树继续分治
然后就没啦
luogu模板
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define M 400001
using namespace std;
int sum,q[M],x,y,z,rt,b[M],maxx=0x3f3f3f3f,n,m,k,d[M],ver[M],head[M],edge[M],nex[M],cnt,vis[M],s[M],c[M];
bool judge[10000001];
void add(int x,int y,int z)
{
ver[++cnt]=y; nex[cnt]=head[x]; head[x]=cnt; edge[cnt]=z;
ver[++cnt]=x; nex[cnt]=head[y]; head[y]=cnt; edge[cnt]=z;
}
void gr(int now,int fa)
{
s[now]=1; int t=0;
for(int i=head[now];i;i=nex[i])
{
if(ver[i]==fa || vis[i]) continue;
gr(ver[i],now);
s[now]+=s[ver[i]];
t=max(t,s[ver[i]]);
}
t=max(t,sum-s[now]);
if(t<maxx) rt=now, maxx=t;
}
void gc(int now,int fa,int x)
{
c[++c[0]]=x;
for(int i=head[now];i;i=nex[i])
{
if(ver[i]==fa || vis[now]) continue;
gc(ver[i],now,x+edge[i]);
}
}
void calc(int now)
{
c[0]=0;
for(int i=head[now];i;i=nex[i])
{
if(vis[ver[i]]) continue;
int u=c[0]+1; gc(ver[i],now,edge[i]);
for(int j=u;j<=c[0];j++)
for(int l=1;l<=m;l++) if(q[l]>=c[j]) b[l]|=judge[q[l]-c[j]];
for(int j=u;j<=c[0];j++) judge[c[j]]=1;
}
for(int i=1;i<=c[0];i++) judge[c[i]]=0;
}
void solve(int now)
{
vis[now]=judge[0]=1; calc(now);
for(int i=head[now];i;i=nex[i])
{
if(vis[ver[i]]) continue;
sum=s[ver[i]]; maxx=0x3f3f3f3f;
gr(ver[i],now); solve(ver[i]);
}
}
int main()
{
scanf("%d%d",&n,&m); sum=n;
for(int i=1;i<n;i++)
scanf("%d%d%d",&x,&y,&z), add(x,y,z);
for(int i=1;i<=m;i++) scanf("%d",&q[i]);
gr(1,0); solve(rt);
for(int i=1;i<=m;i++)
if(b[i]) printf("AYE\n"); else printf("NAY\n");
}
某一天,我突然发现以前写的淀粉质都是错的==
一层的大小不一定是找根时的大小
比如这个x的大小
真的难写
简单一说无非就是记一下模式串前缀哈希值,后缀哈希值,然后尝试匹配
分类讨论的题一定要把柿子全列出来再写程序
对了,而且这道题卡常