7月好题记录

Codeforces 1063 B. Labyrinth

【确定性】给出一个迷宫\((1 \leq n,m \leq 2000)\),求从起点到各个点,能够做到在左移动次数不超过\(x\)次,右移动次数不超过\(y\)次的情况下到达的点的个数。

显然贪心地要求到达每个点时左右移动次数越少越好,但是两个关键字很难维护。而事实上,起点终点确定时,左移动次数确定时右移动次数一定确定。当终点在起点左侧时,最小化左移动次数即可;当终点在起点右侧时,依然最小化左移动次数即可。当然两者都最小化右移动次数也可以。这就告诉我们,我们只需要最小化其中一个就可以了。直接利用重复进队更新的bfs维护即可。

反思:确定性。对于平面距离的理解。

Codeforces 1019 A. Elections

【逆向思维】有\(n\)个人给\(m\)个党投票(\(1 \leq n,m \leq 3000\))。第\(i\)个人给\(p_i\)党投票,可以花\(c_i\)贿赂让他改变投票对象(任意改变)。问最少花多少钱能让1党获胜。

正向思考很难。考虑确定1党最后的得票之后就可以确定达成这样的状态最少花多少钱,因此枚举1党得票,贪心计算最少花费。复杂度\(O(n^2)\)。具体的,设枚举到1党得票为\(k\),则对于所有\(a_i \geq k\),需要削掉,选择花费最少的削。之后如果还凑不到,就选最便宜的人凑就行了。

反思:正向难思考时选择逆向。

Codeforces 777 D. Cloud of Hashtags

【从后往前做】给出\(n\)个字符串,在不改变字符串的顺序的情况下,允许任意删去每个字符串的一段后缀(可以删光),问总共最少删几个字符使所有字符串按字典序排列。

考虑两个字符串的相对关系。要使得前一个字符串比后一个字符串字典序小,那么只需要从前往后扫到第一个不同的地方(或结尾)然后标记一下就好了。于是想到从前往后这样做。但这样会有问题,因为一旦后面的字典序变小,会影响前面的所有。正确的做法是从后往前这样做。

反思:怎样的顺序来做要弄清楚

Codeforces 442 B. Andrey and Problem

【推式子,贪心】有\(n\)个人,第\(i\)个人有\(a_i\)的概率同意,\(1-a_i\)的概率不同意。问怎么选择一些人,使得只有一人同意的概率最大。

假设我们已经选择了一个集合\(S\),则概率为\(\sum\limits_{i \in S}[\dfrac{a_i}{1-a_i}\prod\limits_{j \in S}(1-a_j)]\)。令\(B=\prod\limits_{i \in S}(1-a_i)\)\(S=\sum\limits_{i \in S}\dfrac{a_i}{1-a_i}\)。则概率为\(SB\)

现在考虑加入一个\(a_k\),那么考虑答案的变化量\(\Delta=(S+\dfrac{a_k}{1-a_k}) \cdot B \cdot (1-a_k)-SB=B(1-S)a_k\)。因此只要满足\(S<1\),那么选择\(a_k\)答案就会变大。

那么接下来考虑怎么选择。如果我们贪心地来考虑,那么显然选择最大的\(a_k\)会最优,这样我们对\(a_k\)排序从大到小选择直到\(S \geq 1\)为止,复杂度\(O(n \log n)\)

为什么可以贪心,可以用反证法证明。

反思:数学问题推式子是个很好的选择。思想:计算每一次加入的\(\Delta\)以得到总的答案。

Codeforces 1096 D. Easy Problem

【DP状态定义、决策的思维】给出一个字符串,删除第\(i\)个字符的代价为\(a_i\)。问最少花多少代价使得原串内不存在子序列hard(不是子串,也就是可以不连续)

对于每一个新加进来的字符,如果不是hard中的一个则可以不用管。如果加入的是d,那么我们要么直接破坏这个d,要么破坏前面使得前面不存在har。想让前面不存在har,就要在r加入时做类似的事。因此我们选择DP。令\(dp_{i,j}\)表示前\(i\)个位置,破坏掉长度为\(j\)的前缀(可以不连续)的最小代价。于是根据刚才的两种决策,有\(dp_{i,j}=\min\{dp_{i-1,j-1},dp_{i-1,j}+a_i\}\)。那么答案就是\(\min\{dp_{n,j}\}\)

反思:状态的定义与性质有关。这题还要再想想清楚

Luogu P2336 喵星球上的点名

【工业题,后缀数组转化为区间问题,差分思想】有\(n\)个人,每人有两个字符串。给出\(m\)次询问,每次询问给出一个字符串,问这个字符串在多少个人的那两个字符串中的一个里出现过。询问结束后输出每个人被询问到的次数。

首先将所有人和询问的字符串并在一起(中间要插字符)做SA。每一次询问就对应着后缀排序之后的一段区间,预处理出每一个后缀属于哪个人当做每个点的颜色,问题转化为区间颜色个数,与每个颜色被覆盖的次数。前者直接用莫队解决,后者考虑差分:每次覆盖到,就对答案加上剩余询问个数次贡献,每次离开,就对答案减去剩余询问个数次贡献。

反思:后缀数组总与区间问题联系在一起

Codeforces 988 D. Points and Powers of Two

【结论题】给出一个数列,选取其中最大的一个子集,满足其中任意两个元素满足\(|a_i-a_j|=2^d,(d \geq 0)\)

子集大小不可能超过3!因为对于大小为三的子集,他们一定是等距的,不然两端的两个距离不会是二次幂。因此用个map记录,然后枚举指数暴力判断即可。复杂度\(O(n \log^2n)\)

反思:利用性质大致确定答案的数量级(可能值)

Codeforces 375 B. Maximum Submatrix 2

【由类似题获得思路;贪心】给出一个01矩阵(\(1 \leq n,m \leq 5000\)),可以任意交换行的顺序。求交换后可能的最大全1子矩形面积。

我们知道静态的全1子矩形可以通过维护每个点向左延伸的最长1的个数,然后利用单调栈进行扩展求最值。那么我们不妨还是维护这个东西,然后对于每一列将这个值排个序求解。

反思:既然全1子矩形的问题碰到过,是通过维护延伸求解的。那么这种题应该不会差太远。思路要往这上面靠。

Codeforces 2 B. The least round way

【双价值的处理】给出一个\(n \cdot n\)的矩阵,从左上角走到右下角(向右或向下),经过的数字相乘。怎样走使得得到的结果结尾的0尽量少。

首先处理出每个数的2因子与5因子个数。接着有个重要结论:结尾的0的最小个数,为最小2的路径与最小5路径中的较小值。这样就把双价值的问题转化为单价值的问题了。

反思:双价值总是难以处理的。

Codeforces 463 D. Gargari and Permutations

【建图;问题特性】给出\(k\)个长度为\(n\)排列\(1 \leq n \leq 1000,1 \leq k \leq 5\)),求出LCS。

枚举数对。预处理出每个数对在每个排列中是顺序的还是逆序的。如果对于所有排列某数对都是同一个序的,那么这个数对就是可以作为LCS的一部分的。找出所有这样的数对之后,得到一张\(DAG\),求出最长链即可。

反思:DP的本质是DAG。因此关键是要抓住这张DAG在这里是什么。

Codeforces 449 B. Jzzhu and Cities

【建图;最短路的性质】给出一张带权的无向图。再给出\(k\)条长度\(w_i\)\((1,r_i)\)的路径。问这\(k\)条路径最多能删掉几条,使得删掉之后所有点到1的最短路不变。

将这\(k\)条路径加入图中,跑\(Dijkstra\)。同时每个点统计一个最短路入度。然后依次这\(k\)条路径,如果长度大于相应的最短路那肯定删去。如果恰好等于,那么看最短路入度,大于1则可以删去。然后将最短路的入度减去1.

反思:最短路入度这个概念是第一次遇到。

Codeforces 471 D. MUH and Cube Walls

【字符串差分匹配】修改字符换匹配的定义:两个字符串的所有字符的差都相同。问匹配数。

我们来分析一下这样匹配有什么特殊的性质,发现他们两两相邻的差是一样的。于是我们可以预处理出两个串的差分数组,然后直接去匹配差分数组就可以了。用KMP算法\(O(n)\)完成就可以了。

猜你喜欢

转载自www.cnblogs.com/qixingzhi/p/11237074.html