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
(不是子串,也就是可以不连续)
对于每一个新加进来的字符,如果不是h
、a
、r
、d
中的一个则可以不用管。如果加入的是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)\)完成就可以了。
原文地址:https://www.cnblogs.com/qixingzhi/p/11237074.html