zoukankan      html  css  js  c++  java
  • CF 1394 简要题解

    最近都会做一些 ( m Div1) 套题中 (3000) 分以下的题目。

    A

    直接枚举贪心即可。

    B

    首先不难发现总共可能的 (c) 序列只有 (k!) 种,很明显要暴力枚举所有情况然后快速判断。

    不难发现,判定条件为原图中保留的边会将原图划分成若干个互不相交的简单环,换句话说:所有点的入度与出度均为 (1)

    注意到出度一定为 (1),只需判断所有点的入度为 (1) 即可。

    于是可以得到一个 (mathcal{O(k!n)}) 的做法,但实际上可以直接预处理出出度为 (i) 的点走出第 (c_i) 条边而每个点增加的入度,哈希直接判断即可。

    复杂度 (mathcal{O(k!k + nk ^ 2)})

    实际上对于这类合法方案的计数问题,多数情况下会从找出合法的简单充要条件下手。对于复杂的情形,往往可以找出若干个必要条件组成充要条件。

    C

    可以发现,这些操作本质上是可以将 (0 / 1) 分别增加或减少 (1),或同时减少或增加 (01)

    但因为字串的连续性可能做不到随意删去 (01),只能从构造 (t) 串的角度使得能随意执行上述的本质操作。

    不难发现只需要将 (t) 串构造成 (1111 cdots 00000) 这种形式即可。

    那么现在 (s) 距离 (t) 的大小就之和 (s, t)(0, 1) 数量有关了。

    于是问题可以转化为:给定 (n) 个二元组 ((x, y)) 每次可以使得 (x, y pm 1)(x, y) 同时 (pm 1),求一个二元组 ((x_0, y_0)) 使得这 (n) 个二元组到此二元组最大距离最小。

    不难发现可以二分答案大小,那么问题又可以转化为这 (n) 个二元组能在 (L) 次内到达的点中是否存在交集。

    直接求交集是不好求的,不妨反过来,考虑一个二元组能到达的区域对 (x_0, y_0) 的限制,这样求交就很简单了。

    具体地,可以描述为 (x_0, y_0, x_0 - y_0) 的上下界。

    需要注意的是,(t) 不能为空串。

    复杂度 (mathcal{O(n log n)})

    对于这类操作性的问题,如果发现可以将操作简化或合并不失为一个好的选择。

    同时,每当自己发现一条性质以后,一定要思考这个问题能否转化为一个本质相同的更为简单的问题,尝试用简化的语言描述这个得到的新问题。

    注意该做法中区域求交的方式,这是一种通用做法。同时,如果出现二元组能进行两个维度的变化时,可以尝试放到坐标轴下更为直观地观察此问题。

    D

    首先,一条合法链的两种情况本质上是相同的,可以合并为一种:

    不妨对于一条边 ((u, v)(b_u > b_v)),看作是 (u ightarrow v) 的一条有向边,那么一条合法链就是一条连续的有向链。

    那么对于 (b_u = b_v) 的情况呢?不难发现其双向都可以,先不考虑这种情况。

    继续观察可以发现,一个点对答案的贡献就是经过其的链数乘权值。那么对于 (i ightarrow u ightarrow j) 就能合并这两条边减少一次贡献,那么一个点对答案的贡献就是 (max(in_u, out_u) imes a_u)

    接下来考虑 (b_u = b_v) 的情况,需要我们确定这种边的方向最小化总贡献。

    可以发现,对于一个点 (u) 只关乎其儿子 (v(b_u = b_v)) 与其的边的方向,不妨设计一个 (dp),令 (f_{u, 0 / 1}) 表示 (u) 与其父亲的连边向下还是向上。

    那么转移可以被刻画为一个新的问题:从每个二元组 ((a_i, b_i)) 中选择一个元素出来,最终贡献为 (sum d_i + max(c_0 + c_a, c_1 + c_b) imes a_u) 其中 (d) 为选择的序列,(c_0, c_1, c_a, c_b) 分别代表选择的 (a, b) 个数及开始已经确定方向的选择个数。

    因为变量过多,不妨枚举 (c_0) 的数量,那么此时 (c_0, c_1, c_a, c_b) 数量均已确定,问题近一步转化为:

    从每个二元组 ((a_i, b_i)) 中选择一个元素出来,恰好满足选择的 (a, b) 个数分别为 (c_0, c_1),最小化 (sumlimits_{i in A} a_i + sumlimits_{i in B} b_i(|A| + |B| = m))

    这是一个经典问题,即为最小化:(sum a_i + sumlimits_{i in B} b_i - a_i(|A| + |B| = m)),只需选取最小的 (c_1)(b_i - a_i) 即可。

    复杂度 (mathcal{O(n log n)})

    该做法的第一步将本质相同的合法状态合并成了一种,这种转化方式值得学习。

    注意变量较多是可以枚举其中一个或若干个,逐个击破。

    最后这个经典的问题告诉我们,将最优化问题写成一个式子,对答案进行变形转化所求。

  • 相关阅读:
    【FROM】java控件重绘AWT/SWINGPainting in AWT and Swing (EN)
    linux yum使用管理详细使用
    远程控制 vc++实现
    java 鼠标事件Dragged和Moved 及java显示GIF在JLabel、JButton
    C语言字符串函数大全
    C# 训练场(四)创建系统热键,并向活动窗口输入信息
    潜移默化学会WPF(样式) DataGrid(转载)
    时间查询
    Sqlserver2012 根据数据库mdf文件生成log文件,解决无法附加mdf文件
    我知道的一些 ”运行“ 窗体下的命令,个人使用
  • 原文地址:https://www.cnblogs.com/Go7338395/p/14253321.html
Copyright © 2011-2022 走看看