Shik and Travel

题目传送门

第一次过黑题,才打了48行
发 现 每 一 条 边 只 能 且 必 须 遍 历 两 遍 , 手 动 模 拟 或 直 接 证 明 可 以 知 道 一 个 结 论 发现每一条边只能且必须遍历两遍,手动模拟或直接证明可以知道一个结论
如 果 遍 历 到 一 颗 子 树 , 那 么 就 一 定 要 把 这 棵 子 树 遍 历 完 才 能 遍 历 下 一 棵 如果遍历到一颗子树,那么就一定要把这棵子树遍历完才能遍历下一棵
这 样 就 很 容 易 想 到 利 用 树 形 D P 的 方 法 , 同 时 又 具 有 单 调 性 , 可 以 用 二 分 , 记 二 分 的 数 值 为 v a l u e 这样就很容易想到利用树形DP的方法,同时又具有单调性,可以用二分,记二分的数值为value DP,value
发 现 这 个 题 目 的 树 是 一 个 二 叉 树 , 而 且 不 是 叶 子 就 一 定 有 2 个 儿 子 的 那 种 发现这个题目的树是一个二叉树,而且不是叶子就一定有2个儿子的那种 2
可 以 用 一 个 f [ x ] 表 示 从 x 点 出 发 遍 历 到 a 叶 子 的 长 度 , 结 尾 再 遍 历 到 b 叶 子 的 长 度 的 所 有 满 足 ≤ v a l u e 的 值 ( 用 v e c t o r 储 存 ) 可以用一个f[x]表示从x点出发遍历到a叶子的长度,结尾再遍历到b叶子的长度的所有满足\leq value的值(用vector储存) f[x]xabvalue(vector)
只 需 要 用 儿 子 节 点 转 移 即 可 只需要用儿子节点转移即可
考 虑 如 何 转 移 考虑如何转移
记 一 颗 树 的 一 个 儿 子 为 l s , 另 外 一 个 为 r s , 两 个 点 的 边 分 别 为 l v , r v . 很 显 然 , f [ x ] 的 ( a , b ) 一 个 在 l s 子 树 内 , 一 个 在 r s 子 树 内 记一颗树的一个儿子为ls,另外一个为rs,两个点的边分别为lv,rv.很显然,f[x]的(a,b)一个在ls子树内,一个在rs子树内 ls,rs,lv,rv.,f[x](a,b)lsrs
f [ x ] = { ( f [ x . l s ] . l f t + l v , f [ x . r s ] . l f t ) ( f [ x . l s ] . l f t + l v , f [ x . r s ] . r g h ) ( f [ x . l s ] . r g h + l v , f [ x . r s ] . l f t ) ( f [ x . l s ] . r g h + l v , f [ x . r s ] . r g h ) 这 里 的 f 是 个 结 构 体 , 代 表 着 所 有 的 点 对 , l f t 表 示 点 对 的 左 值 , r g h 表 示 点 对 的 右 值 f[x]=\begin{cases}(f[x.ls].lft+lv,f[x.rs].lft)\\(f[x.ls].lft+lv,f[x.rs].rgh)\\(f[x.ls].rgh+lv,f[x.rs].lft)\\(f[x.ls].rgh+lv,f[x.rs].rgh)\\这里的f是个结构体,代表着所有的点对,lft表示点对的左值,rgh表示点对的右值\end{cases} f[x]=(f[x.ls].lft+lv,f[x.rs].lft)(f[x.ls].lft+lv,f[x.rs].rgh)(f[x.ls].rgh+lv,f[x.rs].lft)(f[x.ls].rgh+lv,f[x.rs].rgh)f,lftrgh
画 个 图 就 能 明 白 : 画个图就能明白:
在这里插入图片描述
但 是 很 容 易 就 想 到 这 样 很 显 然 是 不 可 能 全 部 转 移 , 因 为 方 案 数 实 在 太 多 了 , 但 是 一 定 会 有 很 多 的 冗 杂 的 信 息 考 虑 怎 么 优 化 , 可 以 发 现 对 于 两 个 决 策 ( v 1 a , v 1 b ) ) , ( v 2 a , v 2 b ) , 如 果 v 1 a < v 2 a , v 1 b < v 2 b , 那 么 后 面 的 那 个 决 策 一 定 是 没 有 必 要 的 但是很容易就想到这样很显然是不可能全部转移,因为方案数实在太多了,但是一定会有很多的冗杂的信息\\考虑怎么优化,可以发现对于两个决策(v1_a,v1_b)),(v2_a,v2_b),如果v1_a<v2_a,v1_b<v2_b,那么后面的那个决策一定是没有必要的 (v1a,v1b),(v2a,v2b)v1a<v2a,v1b<v2b,
那 么 这 样 子 的 优 化 后 , 排 序 一 定 是 具 有 单 调 性 的 , 假 设 按 第 一 关 键 字 排 序 , 就 是 第 一 个 数 持 续 递 增 , 第 二 个 数 持 续 递 减 , 那 么 就 可 以 发 现 对 于 两 个 儿 子 合 并 的 时 候 就 可 以 用 双 指 针 优 化 那么这样子的优化后,排序一定是具有单调性的,假设按第一关键字排序,就是第一个数持续递增,第二个数持续递减,那么就可以发现对于两个儿子合并的时候就可以用双指针优化 ,
时 间 复 杂 度 O ( n l o g 2 n ) 时间复杂度O(nlog^2n) O(nlog2n)不会证

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
#define ll long long
#define P pair<ll,ll>
#define ls lb[x].son
#define rs rb[x].son
#define lv lb[x].v
#define rv rb[x].v
#define fi first
#define se second
struct cow{int son,v;}lb[N],rb[N];
int n,a[N];vector<P>f[N];
void dfs(int x,ll v){
	f[x].clear();
	if(!ls){f[x].push_back((P){0,0});return ;}
	vector<P>now;dfs(ls,v);dfs(rs,v);
	for(int o=0;o<2;o++){
		ll tmp=v-lv-rv;
		for(int i=0,j=0;i<f[ls].size();i++){
			while(j+1<f[rs].size()&&f[rs][j+1].fi+f[ls][i].se<=tmp)j++;
			if(j>=f[rs].size()||f[rs][j].fi+f[ls][i].se>tmp)continue;
			now.push_back((P){f[ls][i].fi+lv,f[rs][j].se+rv});
		}swap(lv,rv);swap(ls,rs);
	}sort(now.begin(),now.end());
	for(int i=0;i<now.size();i++){
	  if(!f[x].empty()&&f[x].back().se<=now[i].se)
	  continue;f[x].push_back(now[i]);
	}
}
bool check(ll mid){
	dfs(1,mid);return f[1].size()>=1;
}
int main()
{
	scanf("%d",&n);ll l=0,r=0;
	for(int i=2;i<=n;i++){
		int fa,v;scanf("%d%d",&fa,&v);
		if(lb[fa].son)rb[fa]=(cow){i,v};
		  else lb[fa]=(cow){i,v};r+=v;
	}
	while(l<r){
		ll mid=l+r>>1;
		if(check(mid))r=mid;
		  else l=mid+1;
	}
	printf("%lld",l);return 0;
}
《餐馆点餐管理系统——基于Java和MySQL的课程设计解析》 在信息技术日益发达的今天,餐饮行业的数字化管理已经成为一种趋势。本次课程设计的主题是“餐馆点餐管理系统”,它结合了编程语言Java和数据库管理系统MySQL,旨在帮助初学者理解如何构建一个实际的、具有基本功能的餐饮管理软件。下面,我们将深入探讨这个系统的实现细节及其所涉及的关键知识点。 我们要关注的是数据库设计。在“res_db.sql”文件中,我们可以看到数据库的结构,可能包括菜品表、订单表、顾客信息表等。在MySQL中,我们需要创建这些表格并定义相应的字段,如菜品ID、名称、价格、库存等。此外,还要设置主键、外键来保证数据的一致性和完整性。例如,菜品ID作为主键,确保每个菜品的唯一性;订单表中的顾客ID和菜品ID则作为外键,与顾客信息表和菜品表关联,形成数据间的联系。 接下来,我们来看Java部分。在这个系统中,Java主要负责前端界面的展示和后端逻辑的处理。使用Java Swing或JavaFX库可以创建用户友好的图形用户界面(GUI),让顾客能够方便地浏览菜单、下单。同时,Java还负责与MySQL数据库进行交互,通过JDBC(Java Database Connectivity)API实现数据的增删查改操作。在程序中,我们需要编写SQL语句,比如INSERT用于添加新的菜品信息,SELECT用于查询所有菜品,UPDATE用于更新菜品的价格,DELETE用于删除不再提供的菜品。 在系统设计中,我们还需要考虑一些关键功能的实现。例如,“新增菜品和价格”的功能,需要用户输入菜品信息,然后通过Java程序将这些信息存储到数据库中。在显示所有菜品的功能上,程序需要从数据库获取所有菜品数据,然后在界面上动态生成列表或者表格展示。同时,为了提高用户体验,可能还需要实现搜索和排序功能,允许用户根据菜品名称或价格进行筛选。 另外,安全性也是系统设计的重要一环。在连接数据库时,要避免SQL注入攻击,可以通过预编译的PreparedStatement对象来执行SQL命令。对于用户输入的数据,需要进行验证和过滤,防止非法字符和异常值。 这个“餐馆点餐管理系统”项目涵盖了Java编程、数据库设计与管理、用户界面设计等多个方面,是一个很好的学习实践平台。通过这个项目,初学者不仅可以提升编程技能,还能对数据库管理和软件工程有更深入的理解。在实际开发过程中,还会遇到调试、测试、优化等挑战,这些都是成长为专业开发者不可或缺的经验积累
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值