[题解]gdfzoj 723 | 2020提高训练12T3
首先,吐槽一下这道题:
为啥去买东西还往回走的啊,为啥买水果还能往回走的啊,奇怪的买东西方式增加了
第一次看到这道题的时候,没理解题意,以为不能回头走,想着树剖秒了
但是样例说明,可以往后走 自闭
正片
之后思考了一下,发现题目实际是求这个东西:存不存在有 个连通的点,其中有 个水果店
把样例图建出来之后发现了一个奇怪的现象,即
在同一棵子树里选固定个商铺,其中水果店的个数在一个区间里
(我也不知道表达地是否准确,反正差不多理解就行)
然后感觉可以 试一下
设 表示 节点的子树中选取 个点(包括 节点) , 的情况下最多的水果店数
设 表示 节点的子树中选取 个点(包括 节点) , 的情况下的最少水果店数
更新:
设 为 的子树大小
对于 且
这个地方有点类似于 背包(反正我是这么理解的)
需要注意的坑点是 从大到小枚举 , 从小到大枚举,因为不能覆盖之前的
得到 和 之后,就意味着从 至 的区间是合法的
所以将 和 的值更新到 和 里就可以了
假设询问为
表示 可能的最大值
表示 可能的最小值
询问的时候判断 是不是在 和 之间就可以了
然后另外的一些坑点:
- 要边 边更新,因为如果先预处理 的话会更新时出错(自行思考)
2.要先把 和 赋值无限大
然后就没啥好说的了吧。。
至于复杂度嘛,我也不知道,不过目测是 的 ( * * )
完结撒花
代码:
#include<bits/stdc++.h>
namespace my_std
{
using namespace std;
#define int long long
#define R register
#define rep(i,a,b) for (R int i=(a);i<=(b);i++)
#define drep(i,a,b) for (R int i=(a);i>=(b);i--)
#define go(u) for (R int i=head[(u)];i;i=e[i].nxt)
#define pf printf
#define writeln(x) write(x),putchar('\n')
#define writesp(x) write(x),putchar(' ')
#define mem(x,v) memset(x,v,sizeof(x))
typedef long long ll;
const int INF=0x7fffffff;
inline int read()
{
int sum=0,f=0;
char c=getchar();
while (!isdigit(c))
{
f|=(c=='-');
c=getchar();
}
while (isdigit(c))
{
sum=(sum<<1)+(sum<<3)+(c^48);
c=getchar();
}
return f?-sum:sum;
}
void write(int k)
{
if (k<0) putchar('-'),k=-k;
if (k>=10) write(k/10);
putchar(k%10+'0');
}
inline void chkmax(int &x,int y)
{
if (x<y) x=y;
}
inline void chkmin(int &x,int y)
{
if (x>y) x=y;
}
}
using namespace my_std;
const int N=410;
int n,q,cnt,head[N];
int f_max[N][N],f_min[N][N];
int dpmax[N],dpmin[N];
int fruit[N],size[N];
struct edge
{
int to,nxt;
}e[N<<1];
inline void add(int u,int v)
{
e[++cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
inline void dfs(int u,int fa)
{
size[u]=1;
f_max[u][1]=f_min[u][1]=(fruit[u])?1:0;
go(u)
{
int v=e[i].to;
if (v==fa) continue;
dfs(v,u);
drep(k,size[u],1) rep(j,1,size[v])
{
chkmax(f_max[u][k+j],f_max[u][k]+f_max[v][j]);
chkmin(f_min[u][k+j],f_min[u][k]+f_min[v][j]);
}
size[u]+=size[v];
}
}
signed main()
{
n=read(),q=read();
rep(i,1,n-1)
{
int u=read(),v=read();
add(u,v),add(v,u);
}
rep(i,1,n) fruit[i]=read();
mem(dpmin,0x3f);mem(f_min,0x3f);
dfs(1,0);
rep(u,1,n) rep(i,1,size[u])
{
chkmax(dpmax[i],f_max[u][i]);
chkmin(dpmin[i],f_min[u][i]);
}
rep(i,1,q)
{
int x=read(),y=read();
if (dpmin[x]<=y&&dpmax[x]>=y) pf ("Yes\n");
else pf ("No\n");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端