省选计划(第二周)
知识回顾:
-
巩固:二分,倍增,优化DP,莫队,分数规划,网络流,二分图,贪心,set/map,KMP
-
深入研究:分治(线段树分治),后缀数组,费用流
-
简单了解/没学明白:线性基,边分治,数位DP,博弈论
练题:
直接模拟复杂度 ,显然会超时,于是考虑倍增。
定义 表示从 i 这条线段走 次所能到达的最远的线段编号。
转移显然,。
为了方便,可以断环为链。
复杂度 。
Yet Another Minimization Problem
神仙题。
第一眼看上去就是 DP。
定义 表示当前点 i,分 j 段的最小费用。
然后发现复杂度 ,直接 T 飞,需要优化。
我们发现 j 那一维可以滚掉,也就是只考虑第一维,然后做 j 次就行了,下面称 为 。
对于 ,我们发现当 j 固定时,i 越小,值越大 (废话。
接下来最关键的一步就是证明转移的最优决策点是单调不降的。
我们考虑反证法。
定义 u 为当前点 i 的最优决策点,v 为 i+1 的最优决策点。
那么
若 v < u,则对于 i+1 应当满足:
即:
根据之前发现的单调性,显然可以得出 ,即 。
所以移项可得 ,与前者矛盾,证毕。
接下来就可以用分治来优化了。
定义 为当前处理的区间 和可能的最优决策点所在区间 。
对于一个这样的函数,我们可以暴力找到 的最优决策点 p, 然后递归下去。
那么问题来了,怎么快速求出 呢?直接莫队就行了!
复杂度 。
分数规划+树形背包。
可以根据推荐关系建出一颗树,然后如果选了一点,则该点到根上的所有点都必须选。
二分 mid,定义每个结点的权值,然后判断选 k+1 个节点的最大值是否大于 0。
设 为当前节点 i,在其子树内选了 j 个节点,最大点权和为多少。
转移方程为 。
初始化为 ,,其余皆为 -inf。
然后我们发现这个 DP 的复杂度貌似是 。
但将各种限制条件加上后就变成了 。本人很菜,没法证明。
所以最终复杂度为 。
求比值,分数规划。
对于每一个男生向所有女生连一条容量为 1,费用为 的边,原点 s 向所有男生连一条容量为 1,费用为 0 的边,所有女生向汇点 t 也连一条容量为 1,费用为 0 的边。
然后跑一边 KM 或者最大费用最小流就行了。
复杂度 。
线段树分治。
我么发现添加物品容易,而删除物品难。
考虑把物品出现和删除的时间点表现在数轴上,那么一个物品的贡献就在这个区间内。
假设一共有 cnt 个查询操作,则我们建一棵大小为 cnt 的线段树。
然后对于每一个物品,将其区间拍在线段树上。
为了方便操作,可以在每个线段树结点上开一个 vector 存储被哪些物品覆盖。由于一个物品只会体现在 log 个结点上,所以 vector 的总空间为 ,不用担心 MLE。
最后遍历整棵线段树,对当前结点 vector 内的元素背包,然后再将 DP 数组下传给左右儿子。
最后每个叶子节点都对应一个询问,直接输出就行了。
复杂度 。
模板题。
线段树分治还是该咋写咋写,二分图的判断需要注意一下。
常见的方法是黑白染色,但这里不行,要用拓展域并查集。
也就是把一个点 u 拆成 u 和 u+n 两个点,每次连边只连两个不同域内的点,如果发现 u 和 u+n 在一个集合里,则说明有奇环,不是二分图。
线段树分治返回的时候,并查集显然也要返回初始状态,所以不能进行路径压缩,为了使复杂度有保证,改用安秩合并。
撤回时可以借助栈。
复杂度 。
可以说是模板题的进阶吧。
首先并查集要变成 k 个,对于每一种颜色都维护一下。
考虑一条边被染成某种颜色所处的时间段为 ,那么会有两种情况。
1.染上去了,更新颜色。
2.没染上去,还是之前的颜色。
最后跑一边 dfs 就行了。
复杂度
还是线段树分治。
每次给一条边,如果没有就添加,如果存在就删除。
于是可以转化成一段存在的区间,可借助 map 记录是否存在。
剩下的就是板子了。
复杂度 。
考场代码写得就是一坨屎,最后弃了。
我们可以定义一个 multiset 来存当前 m 个数。
添加元素:如果插入后在前 k 小,则减去第 k 个,加上这个数,否则不进行任何操作。
删除元素:如果要删除的元素在前 k 小,则减去这个数,加上第 k+1 个数,否则不进行任何操作。
复杂度 。
题目要求我们求这个式子:
可以从高到低考虑每一位。
如果当前这些数的第 k 位都相同,则可以忽略这一位。
否则的话可以将这些数分成两类,一类为 0,一类为 1,然后递归处理。
复杂度 。
背包+分治。
最朴素的做法是分组背包,对于每一个数组,考虑其每一个前缀,复杂度 。
然后我们发现这些数组有着很好的性质,那就是不降。
于是就可以推出最佳的选法一定是全选若干个再加上一个选一些的,证明如下。
假设有两个数组都选了一部分数,其最后一个数分别为 a 和 b,且 a > b。
则显然在 a 后面继续选会更优。
接下来考虑分治。
对于当前区间 计算出 mid,将 做一遍 01 背包,然后递归 。
同理 也需要递归一遍。
如果 ,那么枚举一下数组 l 选的长度,更新一下就好了。
最后输出最大值。
复杂度 。
KMP简单题。
对于两个字符串a、b,我们要求出最大的 i 使得 与 相等。
然后可以把 b 接在 a 前面,中间隔上一个 ,跑一边 KMP 求出 border,然后去掉公共部分把 b 拼上就行了。
复杂度 。
很久以前就学过,但没太学懂,经过董老师的一番讲解,我豁(geng)然(jia)开(meng)朗(bi)。
定义 为 s 的所有后缀中字典序第 i 小的编号。
为后缀 i 的排名。
两者间关系为:
可以用倍增求解。
任何长 的子串都可以表示成两个长为 的子串的拼接。
若知道所有长 的子串的排名,则长 的子串可以用一个二元组表示。
假如我们用 sort 进行排序,复杂度为 ,不太 nice。
所以考虑用基数排序优化掉一个 log,即先对第二个排序,再对第一个排序。
求出 height 数组,然后用总方案数减去所有 height 数组之和,即:
费用流题。
先拆点,分成入点和出点。
对于每一个点 ,从入点向出点连一条容量为 1,费用为 的边,和一条容量为 k-1,费用为 0 的边。
然后 和 连一条容量为 k,费用为 0 的边, 和 也连一条容量为 k,费用为 0 的边。
最后跑一边最大费用最大流就行了。
很麻烦的费用流。
我们可以给订单拆点,容量为 inf,费用为该订单的收益。
然后给起点 1 也拆一下,容量为 k,费用为 0。
如果起点到某个订单的起点的时间符合要求,则连一条容量为 inf,费用为 。
如果某个订单能按时回到起点 1,则连一条容量为 inf,费用为
接着两两枚举订单,如果订单 i 能按时到达订单 j,则连一条容量为 inf,费用为 。
最后跑一边费用流。
模拟赛:
USACO
AK了铜组,银组差十秒AK(可恶。
一周过后终于出结果了,没晋级......
铜组:
排序,对于每个值算一下就好了,比较简单。
复杂度 。
[USACO22DEC] Feeding the Cows B
神奇的贪心。
首先我们可以把一块草的贡献理解为一个 的区间,然后可以从左到右枚举每一头牛。
如果当前牛被区间覆盖,忽略。
否则的话以这头牛为左端点安排一个区间。
需要注意的是如果 ,那么可以先忽略这头牛,都处理完后从后往前找到第一个空位安排一下就行了(直观感受是对的,但我不会证明......
复杂度 。
P8899 [USACO22DEC] Reverse Engineering B
有意思的题。
判断有没有说谎其实就是看能否构造出可行解。
可以发现,if/else if/else 的组合的实际意义是每次根据某位的特性删去一部分字符串,而能够删除的条件是:当前拥有这个特性的所有字符串所返回的值相同。
接下来就好办了,我们采用贪心的策略。
如果当前位能够排除一波,那就执行一下。
为什么要立刻执行呢?因为如果一位能排除,那么不管怎么删除字符串都不会对其造成影响,反之的话就有可能使其成立。
所以这样的贪心是正确的。
复杂度 。
银组:
P8900 [USACO22DEC] Barn Tree S
第一眼看上去没什么思路。
考虑以 1 为根,计算其所有子树内干草的数量,然后可以判断出从节点 u 和它的父亲之间需要运多少草。假如需要从 u 向 运 w 捆草,那么连一条 。
可以发现这是一个 DAG,于是跑一边拓扑排序就行了。
复杂度 。
P8901 [USACO22DEC] Circular Barn S
考场上因为一些小细节没调出来!!!
定义 表示有 i 头牛,先手能否赢。
定义 表示有 i 头牛,如果双方都采取最优策略,需要多少次结束。
先用埃氏筛找出所有质数,然后对于递推求出 f 和 g。
如果存在 j,使得 且 ,则 ,否则 。
如果 ,则
否则
然后发现 T 飞了。
但是我们通过打表发现,如果 ,则 ,否则 。对于所有偶数,。
于是只需要考虑 i 为奇数的情况。
因为所有奇数的 i 都有 ,而满足 的 j 必为 4 的倍数且 具有单调性,所以我们可以从大到小枚举质数,找到第一个满足 的 k,令 。
最后判断输赢的时候只需要对于每一个数找到 最小且最靠前的 i,并判断 即可。
复杂度很玄学,但是能过。
P8902 [USACO22DEC] Range Reconstruction S
别看题面很唬人,其实是个诈骗题。
我们知道相邻点的差的绝对值 r。如果 枚举显然不行。
假如我们有三个数,后两个的值不同且已经确定了(如果相同的话就可以合并成 1 个点),可以发现第一个数的值是唯一确定的。
于是我们就可以从后往前构造。
令 ,然后对于每一位的两种情况都分别试一下,取满足的一种就行了。
复杂度 。
A计划
太难了,打完部分分跑路了。
最终得分 20+20+40=80 rk15
贴一下官方题解。
对于每一个,考虑给每条边一个定向,如果,那么另,否则。
那么如果一条路径上边的方向都是从或者,,否则。
考虑边分治,每次左边的所有边指向根节点,右边的所有边从根指向儿子即可。
或者点分治,每一层套一个二进制分组。二进制位为的从下往上指,否则从上往下指。
ps:由于点分治不熟,不订正了。
显然,可以把两个数都填满前导零,答案也不会变。
最好的方法就是把按位排序,按位排序,依次相减。
也就是计算表示到的所有数中,数位第大的数大小为的方案数。
考虑枚举,数位dp。区间的数可以转化为前缀的数。
计算表示考虑了前位,比小的有个,和一样的有个。
为了比较和的大小,还要记录一位表示前位是否和一样。
最简单的一道题,但博弈论并不是我擅长的板块,所以考场弃了......
显然,如果初始时找不到的没有任何一个棋子的矩阵,那么先手必败。
如果能找到一个点,使得在这个点上放一枚棋子,导致找不到的没有任何一个棋子的矩阵,那么先手必胜。
除去这两种情况,初始局面至少会存在两个不相交的没有棋子的的矩阵。以及必败条件可以改成操作后使得找不到两个的矩阵,使得这两个矩阵全空且没有交。
那么考虑最后一步,肯定是只剩下了两个没有交的的矩阵。及一共有个位置没有棋子,其他位置都有棋子。
根据初始空位的奇偶性,很容易得出最后一步是谁,从而得出谁必胜。
复杂度 。
本文作者:HQJ2007
本文链接:https://www.cnblogs.com/HQJ2007/p/17561592.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下