淀粉质

主要思想就是每次找一个根使其任意一个子树大小小于(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
"); else printf("NAY
"); 
} 

某一天,我突然发现以前写的淀粉质都是错的==

一层的大小不一定是找根时的大小

比如这个x的大小


[SDOI2016]模式字符串

真的难写

简单一说无非就是记一下模式串前缀哈希值,后缀哈希值,然后尝试匹配

分类讨论的题一定要把柿子全列出来再写程序

对了,而且这道题卡常

原文地址:https://www.cnblogs.com/ZUTTER/p/10345729.html