CSP2019 题解
CSP2019 题解
D1T1 格雷码(code)
题目传送门
题解
按照题意模拟就可以了。
对于第 \(i\) 位,如果 \(k \geq 2^i\) 那么这一位就是 \(1\),然后把 \(k\) 变成 \(2^{i + 1} - k - 1\)。否则这一位为 \(0\),\(k\) 不变。
代码
https://loj.ac/submission/687508
D1T2 括号树(brackets)
题目传送门
题解
考虑在每一个点 \(i\) 处求出从根到 \(i\) 的括号序列中的所有后缀的合法数量 \(f_i\),其余的子串的贡献可以直接从父亲处得到。
维护一个栈存储从根到 \(i\) 的没有被匹配的左括号的位置 \(x\),那么显然如果 \(i\) 上是右括号,那么 \(f_i = f_x + 1\),否则 \(f_i = 0\)。
记得在每一个点的处理中记录被弹掉了哪个点,方便回溯。
代码
https://loj.ac/submission/687509
D1T3 树上的数(tree)
题目传送门
题解
作为从根本上把 CSP 难度推向弱胜省选难度的题目,这道题需要分成好几块来讲。
菊花图
菊花的部分分很简单(我又没想出来)。
很容易发现把某一个连接根的边断掉以后,这个点的点权会和根交换,于是这个点的点权就变成了上一个被断的边的点权。
于是可以发现所有的点之间存在这样的关系:
\[
\text{根} \to v_1 \to v_2 \to \cdots \to v_{n - 1} \to \text{根}
\]
也就是说,点权的移动形成了环的关系。我们只需要构造出这个环。
维护很多个链,从小到大枚举每一个点权,找到对应的点,它应该连向目前是链底的一个点中编号最小的点。注意只有在一条链的点数已经满了的时候才可以形成环。
这个可以用并查集或者把链缩成"链底 \(\to\) 链顶"的格式来维护。
这个部分分的代码:https://loj.ac/submission/687489 的 Task2。
链
在链上,如果想要把 \(x\) 上的点权移动到 \(y\),那么需要满足如下条件:
那么对于 \(x\):两个邻边中朝向 \(y\) 的边必须是第一个断掉的。
对于中间的点:两个邻边中朝向 \(x\) 的边必须要比 \(y\) 先断。
对于 \(y\):两个邻边中朝向 \(x\) 的边必须是最后一个断掉的。
于是我们只需要维护每个点的两个邻边的断边顺序即可。从小到大枚举点权,从对应的点上来一次 \(dfs\),可以一边扫一遍判断合不合法,找到最小的可以移动到的点就可以了。
这个部分分的代码:https://loj.ac/submission/687489 的 Task3。
Full
可以发现,对于一个点来说,和菊花类似,以它为根的整棵树中,每一个子树中的点权的去往顺序也依然是形成了一个链的关系:
\[
\text{根} \to v_1 \text{的子树} \to v_2 \text{的子树} \to \cdots \to v_{n - 1} \text{的子树} \to \text{根}
\]
这个链的关系既是点权的移动顺序,也可以表示删边顺序,就是先删 \(v_1\),再删 \(v_2\)……
对于一条路径 \(x \to y\),要把 \(x\) 上的点权移动到 \(y\),那么和链类似,我们可以做出如下的限制:
对于 \(x\):邻边中朝向 \(y\) 的边必须是第一个断的;
- 对于中间的点:领边中朝向 \(x\) 的点必须恰好在 \(y\) 前一个断。
对于 \(y\):领边中朝向 \(x\) 的边必须是最后一个断的。
我们考虑如何用上面的链的关系来表达断边顺序:
\(e\) 是第一个断的:\(rt \to e\);
- \(e\) 是最后一个断的:\(e\to rt\);
\(e_1\) 恰好比 \(e_2\) 前一个断:\(e_1 \to e_2\)。
于是我们就可以对于每个点维护一堆链表来操作,和菊花一样,同样是只有在链满了的时候才可以形成环。
代码
https://loj.ac/submission/687959
D2T1 Emiya 家今天的饭(meal)
这道题没做出来是我一辈子的耻辱。
题目传送门
题解
看上去就很像容斥对吧。
如果我们不考虑“每种主要食材至多在一半的菜(即 \(\lfloor \frac k2 \rfloor\) 道菜)中被使用”的限制的话,那么这个题目显然就是每种烹饪方法的可以做出来的菜的数量 \(+1\) 的乘积再 \(-1\)。
想要如果解决这个限制可以考虑容斥。一半这个特殊的限制非常优美,它使得容斥只需要进行一层就可以了(因为不存在有两个食材同时超过一半)。
于是我们枚举哪一个食材超过了一半,假设这种食材为 \(A\)。那么我们维护这样的东西 \(dp[i][j][k]\) 表示前 \(i\) 个烹饪方式中,其中 \(j\) 个烹饪方式用了食材 \(A\),\(k\) 个没有使用的方案数。\(dp\) 的时候直接类似 \(01\) 背包转移就可以了。
最终的限制条件就是 \(j > k\)。
但是这样做是 \(O(mn^3)\) 的。可以获得 \(88pts\)。
因为我们只需要保证 \(j > k\) 即 \(j - k > 0\),所以我们可以直接维护 \(j - k\) 而不是分开维护 \(j\) 和 \(k\)。
时间复杂度 \(O(mn^2)\)。
代码
https://loj.ac/submission/687509
D2T2
题目传送门
题解
并不会证明,只能抽象理解。
可以发现每一个数的贡献就是要乘上它的所在段的和。所以我们要尽量最小化每一段的和,也就是尽量最小化最后一段的和(因为和是递增的)。
然而这个理解方式非常不严谨。
也许可以这样考虑:
把一个子段划分为两段,如果存在两种可以行的划分方式:前面一段的和为 \(s_1\),后面一段的和为 \(s_2\),中间夹着一个数 \(a\),我们考虑应该把 \(a\) 放进前面还是后面。其中 \(s_1 + a \leq s_2\)。
于是
\[
(s_1 + a)^2 + s_2 ^ 2 = s_1^ 2 +s_2 ^ 2 +2as_1 + a^2\\
s_1^2 + (a + s_2)^2 = s_1 ^ 2 + s_2 ^ 2 + 2as_2+a^2
\]
因为 \(s_1 < s_2\) 所以显然选择前者更优,也就是让后面的那一段小一些更优。
然而这样考虑还是很不严谨,算了自闭了不证了。
这样我们的目标就很明确的:最小化最后一段的和。
令 \(f_i\) 表示前缀 \(1..i\) 的最后一段的和的最小值。转移的时候我们需要保证 \(f_j \leq s_i - s_j\) 其中 \(s_i\) 表示前缀和。
\(f_j \leq s_i - s_j\) 等价于 \(f_j + s_j \leq s_i\)。当满足这个条件时,应该尽量取 \(j\) 大的。
所以如果对于 \(j, k\) 满足 \(f_j + s_j > f_k + s_k, j < k\) 那么 \(j\) 就可以被舍弃了。
同时因为 \(s_i\) 是递增的,所以我们可以维护一个单调栈,其中只保留最后一个满足要求的 \(j\),这个 \(j\) 就是 \(i\) 的决策点。
最后因为答案爆炸了 ll,所以需要开一个 \(128\) 个字节的高精度(使用两个 \(ll\) 实现)。
但是如果直接开的话会把 \(1G\) 的空间限制开炸了,所以我们维护前面的每一个点的决策点,最后只需要用一个 \(128\) 字节的变量统计答案就可以了。
代码
我比较懒,不想写高精度,所以用了 int128(其实高精度也很好写)。
https://loj.ac/submission/687514
D2T3 树的重心(centroid)
题目传送门
题解
考场上想到一个非常繁琐的做法,不敢写。
因为两个联通块并的重心应该在原来的两个块各自的重心之间的链上,所以可以直接在链上二分或者倍增。
但是这样还需要特判一对东西,比如连通块不包含哪个子树啊之类的。很麻烦。
所以考场还是乖乖地写了 \(75pts\)。
后来因为我的 \(75pts\) 算法最后的二叉树内容本身就非常古怪,所以想到了一个和一个可行的正解有不小的交集的做法。
我的二叉树做法大概就是发现一个点的重心只能在这个点为整棵树的根以后的最重的儿子中,(显然)所以在完全二叉树上可以直接暴力跳(每个点深度不超过 \(\log n\))。
后来发现了一个可行的正解也用了这个思路。
既然在最重的儿子的子树里面,那么实际上对于一棵树,重心只能在那条从根连下去的重链里面。
于是我们考虑动态维护每一个点为根的重链,然后在上面倍增跳就可以了。
维护重链的时候,每次选择包括其父亲在内的点中最重的儿子作为重儿子。然后因为我们需要避开一个子树,所以顺便维护一下次重的儿子,在需要避开重儿子时使用。
代码实现中需要先预处理每一个子树的重链的倍增数组,然后换根的时候再维护一个倍增数组(这个倍增数组就可以把父亲作为重儿子)。然后在重链上倍增找到最后一个子树大超过一半的点。
(感觉我讲得语无伦次
代码
https://loj.ac/submission/687516
CSP2019 题解的更多相关文章
- CSP2019题解
CSP2019题解 格雷码 按照生成的规则模拟一下即可. 代码 括号树 看到括号匹配首先想到用栈,然后又在树上就可以想到可追溯化栈. 令\(a_i=1\)表示\(i\)号节点上的括号为(,否则为), ...
- CSP2019 树的重心 题解
本题当然可以通过大力讨论每棵子树的size的大小关系,然后用各种数据结构暴力维护.但是我更倾向于用一种更为性质的做法. 首先讲一下我在考场上想到的做法(没写).就是考虑换根,在换根的过程中计算每一条边 ...
- csp2019 Emiya家今天的饭题解
qwq 由于窝太菜了,实在是不会,所以在题解的帮助下过掉了这道题. 写此博客来整理一下思路 正文 传送 简化一下题意:现在有\(n\)行\(m\)列数,选\(k\)个数的合法方案需满足: 1.一行最多 ...
- CSP2019 树上的数 题解
题面 这是一道典型的部分分启发正解的题. 所以我们先来看两个部分分. Part 1 菊花图 这应该是除了暴力以外最好想的一档部分分了. 如上图(节点上的数字已省略),如果我们依次删去边(2)(1)(3 ...
- CSP2019 Emiya 家今天的饭 题解
这题在考场上只会O(n^3 m),拿了84分.. 先讲84分,考虑容斥,用总方案减去不合法方案,也就是枚举每一种食材,求用它做超过\(\lfloor \frac{k}{2} \rfloor\) 道菜的 ...
- 【CSP2019】题解合集
诈个尸 先挖坑 虽然连去都没去但还是想做做 今年貌似比去年还毒瘤啊... yrx.hjw都进了省队线tql orz (myh:没AK真丢脸 Day1T1 格雷码 Day1T2 括号树 Day1T3 树 ...
- 【比赛题解】CSP2019 简要题解
D1T1 code 签到题,大家都会. 可以从高位往低位确定,如果遇到 \(1\),则将排名取反一下. 注意要开 unsigned long long. #include <bits/stdc+ ...
- [题解]CSP2019 Solution - Part B
\(\text{orz}\) 一波现场 \(\text{A}\) 掉 \(\text{D1T3}\) 的神仙 D2T3 centroid Solution 考虑每个点 \(u\) 作为重心的贡献 假设 ...
- [题解]CSP2019 Solution - Part A
至于为什么是 \(\text{Part A}\) 而不是 \(\text{Day 1}\) 那是因为 Day1 T3 还没改 (那这六题的 \(\text{solution}\) 就按难度顺序写吧) ...
随机推荐
- leetcode-mid-others-621. Task Scheduler
mycode 53.01% 这个题在纸上画一画就知道啦,只要出现次数最多的字母能够满足要求,其他更少的字母穿插在其中,间隔就更满足<n啦,当然,最后不要忘记加上尾巴哦,尾巴和出现次数最多的字 ...
- 使用collection:分段查询结果集
1.在人员接口书写方法 public List<Employee> getEmpsByDeptId(Integer deptId); 2在人员映射文件中进行配置 <!-- publi ...
- Spring 缓存注解 SpEL 表达式解析
缓存注解上 key.condition.unless 等 SpEL 表达式的解析 SpEl 支持的计算变量: 1)#ai.#pi.#命名参数[i 表示参数下标,从 0 开始] 2)#result:Ca ...
- sqlalchemy 中 desc 的使用
是这样: items = Item.query.order_by(Item.date.desc()).all() 而不是这样: items = Item.query.order_by(desc(Ite ...
- 关于maven项目 启动页面报错 The type java.io.ObjectInputStream cannot be resolved.
这种情况,要修改jdk版本,默认jdk选择 jdk不选jre windows---->perference---->java----->installes jres-----> ...
- python locust 进行压力测试
最近公司项目周期比较赶, 项目是软硬结合,在缺少硬件的情况下,通过接口模拟设备上下架和购买情况,并进行压力测试, 本次主要使用三个接口 分别是3个场景: 生成商品IP, 对商品进行上架, 消费者购买商 ...
- mysql数据库自带数据库介绍
show databases:查看mysql自带数据库有information_schema,mysql, performance_schema, test information_schema数据库 ...
- 应用安全 - Web框架 - Apache Solr - 漏洞汇总
CVE-2019-12409 Date: // 类型: 配置不当导致远程代码执行 前置条件: 影响范围: Solr and for Linux Solr下载:https://www.apache.or ...
- 【windows】windows安全基础
windows安全基础 安全主体 security principal 是可以进行身份验证的实体. 哪个安全主体在要求访问?这个维度可以是用户,计算机和进程.一旦确认以后,系统就会发放SID. 例子: ...
- 【监控实践】【4.1】利用trace实现阻塞跟踪和慢查询跟踪
原文:https://blog.csdn.net/kk185800961/article/details/49252037 分享个SQLServer profiler 的一个技巧吧.很早用过,忘记总结 ...