ZJOI 2015 大赏
做这套题纯粹是为了好玩… 结果惨遭吊打 = =
「ZJOI2015」幻想乡战略游戏
题目链接
解题思路
点分树是不可能的, 这辈子不可能写的. 数据结构又不会, 只能写写模板这样子.
考虑重链剖分.
不妨钦定 $1$ 为根. 记 $s_u$ 为 $u$ 子树内 $d$ 值之和. 对于一条边 $(u, v)$, 如果选择 $v$ 比 $u$ 更优, 也就是最终花费的变化量为负, 即
因此有一个在线段树上二分 DFS 序, 找出最优点 $v$ 的做法.
同时记 $\text{dist}(u)$ 为点 $u$ 到根节点的距离, 那么最小花费可以表示为
前两项很好维护, 记录 $d_v$ 和 $d_v \cdot \text{dist}(v)$ 的和即可.
注意到 $u$ 的子树内的点, 同 $u$ 的 LCA 一定是 $u$, 而其他点和 $u$ 的 LCA 一定在 $u$ 到根的路径上.
考虑使用重链剖分统计这些可能成为 LCA 的点对答案的贡献.
每次 $d_v$ 改变时, 从 $v$ 到根节点依次修改, 将变化量 $e$ 加入子树内包含 $v$ 的节点上. 设这些节点为 $u$, $u$ 的父亲节点为 $f$, 此时对答案贡献的变化即为 $e \cdot \big( \text{dist}(u) - \text{dist}(f) \big)$, 即 $u$ 到 $f$ 的边贡献的变化量. 用线段树维护就好了.
查询直接对统计的这些贡献求和即可.
时间复杂度 $O(n + q \log ^ 2 n)$.
代码实现
1 | // LOJ #2135 |
「ZJOI2015」地震后的幻想乡
题目链接
解题思路
套 Min/Max 容斥结果越想越偏是屑…
这里是一个平民做法.
考虑如何运用提示给出的公式. 模拟 Kruskal 的过程, 假定第 $k$ 次加入边后恰好得到一棵生成树, 那么对答案的贡献为 $\frac{k}{m + 1}$, 同时概率可以用合法方案数除以总方案数得出.
注意到一棵生成树的权值是对所有边取 $\max$. 那么对于一个连通图, 在该连通图恰好连通时内部边权的最大值, 和生成树的边权最大值是相同的, 因此可以从图的连通上考虑.
但是在恰好第 $k$ 次加入边得到连通图的情况不好统计, 做一步转化: 恰好加入第 $k$ 条边后图连通的方案数, 为: 加入这条边前不连通的方案数 - 加入这条边后不连通的方案数.
考虑用状压 DP 来求这个东西. 设 $f(S, i)$ 为当前选择的点集为 $S$, 已经使用了 $i$ 条边, 点集不连通的方案数.
记点集的全集为 $U$, $d(S)$ 为同点集 $S$ 相关的边的个数, 那么答案为
化简, 得
同时, 点集连通的方案数为 $\binom{d(S)}{i} - f(S, i)$, 其中 $d(S)$ 可以通过枚举子集算出, 而点集连通时的方案数在转移 $f$ 时会用到.
点集不连通的情况可看作由一个连通非空子集上加边, 并保证新加入的点中存在不连通情况得出的. 因此有
枚举子集转移即可. 注意转移时, 需要钦定 $S$ 中某个点, 使得 $T$ 必须包含该点, 否则会重复计算一些情况. 实现时可使用 lowbit
.
至于为什么钦点一个点是对的, 可参看 command_block 的题解
时间复杂度大概是 $O(m3 ^ n)$?
代码实现
轻微压行.
1 | // LOJ #2136 |
「ZJOI2015」诸神眷顾的幻想乡
题目链接
解题思路
考虑广义 SAM, 以及不要读错题, 这题没了.
显然本质不同子串个数可以通过 SAM 来求.
注意到一个重要的条件: “一个空地相邻的空地数量不超过 $20$ 个”, 即叶子个数不超过 $20$. 那么从每个叶子开始, 遍历整棵树, 同时建广义 SAM 即可. 本质上大概是在 Trie 上建 SAM?
设叶子个数为 $L$, 那么时间复杂度为 $O(nL)$.
代码实现
1 | // LOJ #2137 |
「ZJOI2015」黑客技术
题目链接
解题思路
玩一个上午结果不如随缘乱敲分高是屑…
奥妙啊.
「ZJOI2015」醉醺醺的幻想乡
题目链接
解题思路
很厉害的一道题, 以及一个很厉害的题解: http://c-sunshine.blog.uoj.ac/blog/563.
如果单位酿酒量 $x$ 只能是整数, 那么就很好解决了: 将费用差分, 根据差分后的结果将原有边拆为 $c_i$, 也就是容量条边.
但是这里的 $x$ 可以是非负实数, 且最后的结果要求没有精度误差. 因此要使用上述题解的做法. 大体是对费用求导, 然后再积分计算…
注意到每次跑网络流时得到的是一个一次函数, 容易在残量网络中得出斜率 $k$ 以及截距 $b$, 通过斜截式就比较容易理解代码中的式子.
以及上述题解代码将半平面上的点和线都写为 pair<frac, frac>
, 我的代码将两者区分开了, 这样就会清晰许多.
记网络流建图时点数为 $V$, 边数为 $E$, 时间复杂度为 $O(n V ^ 2 E)$.
代码实现
1 | // LOJ #2138 |
「ZJOI2015」幻想乡 Wi-Fi 搭建计划
题目链接
解题思路
对着费用流建半天图还调半天结果发现假了是屑…
首先第一问容易有在 $O(nm)$ 的时间复杂度内计算的方法, 下文不再考虑覆盖不到的景点.
先考虑架设点只在一边的情况. 有一个结论: 将架设点和景点分别按照 $x$ 坐标排序, 那么在最优的方案下, 选择的架设点覆盖到的景点一定是排序后连续的一段.
证明大概是利用长方形宽为 $R$, 同时覆盖半径为 $R$, 恰好不能构造出反例吧… 不大会证.png
有了这个条件, 直接记录选择到第几个架设点 DP 即可.
那么架设点在两侧的情况, 直接在 DP 时多记录一维, 即在另一侧选择到第几个架设点, 对于一个景点分别考虑在两侧架设的情况.
具体地, 设 $f(i, j, k)$ 表示已经覆盖到第 $i$ 个景点, 两侧架设点分别选择到 $j$, $k$. 转移比较显然, 看代码理解就好了.
时间复杂度 $O(nm^3)$, 但是跑不满.
代码实现
1 | // LOJ #2139 |