AtCoder Regular Contest 133 题解
\(A\) 题 \(Erase\) \(by\) \(Value\)
给定一个长度为 \(n\) 的数列,你可以确定一个数 \(x\) ,从中删去所有值为 \(x\) 的数,使得剩下的数列字典序最小。
\(1 \le n \le 200000\)
难度评分 \(265\) ,简单贪心题。
字典序最小,等价于越靠前的数字越小,所以在从前往后考虑时,就不必考虑当前位置后面的数字,考虑数列中相邻的两个数
\(a_i,a_{i+1}\) , 如果 \(a_i > a_{i+1}\) ,那么 \(a_{i+1}\) 排在前面必然比排在后面字典序小,这时如果还有删除次数,那么就删除
\(a_i\) 对应的所有数,必然使得字典序最小,正确性显然,时间复杂度 \(O(n)\)。
\(B\) 题 \(Dividing\) \(Subsequence\)
给定两个长度为 \(n\) 的排列 \(P,Q\) ,从两排列中选出下标相同的子序列,使得 \(Q\) 中选出的子序列的每一项都是 \(P\) 中选出的子序列对应那一项的倍数,求这样的最长序列长度。
\(1 \le n \le 200000\)
难度评分 \(1315\) ,比上一题难了几个档次,但其实还是比较套路的题目。
这题我开始的想法是,把 \(P\) 中的数字下标向 \(Q\) 中对应的数字的倍数的下标想成区间,也可以理解为连一条边,这样就转化为了从一些区间中取出一些区间,使得剩下区间两两交集为空的最大区间数,这是一个经典的贪心问题。
但这样做存在一些问题,比如由后向前的对应和由前向后的对应不好区分,于是考虑换个思路。
其实这题是一道叫做友好城市的题目的扩展题,有兴趣的可以去了解。
求最长的序列长度,自然也会想到求 \(LIS\) ,在这个问题中,如果不把之前位置间的对应想成区间,而是想成一个数对,那么形式化地,有如下转化:
有数对 \((i_1,j_1),(i_2,j_2)......(i_k,j_k)\) 这么一些数对,选出最多的数对,使得选出的数对 \(i,j\) 都单调递增。
这种问题的一类通用解法是(包括友好城市那题也是如此),按照一维排序,剩下的一维求最长上升子序列。
但此处 \(i,j\) 都是有重复数字的,如果只单纯的按 \(i\) 排序,必然会出现问题,注意到问题在于 \(i\) 相同的数对是不能同时选的,那应该用怎样的排序方式才能避免这种情况呢?考虑 \(LIS\) 的条件,必然是从前面的一个比当前小的数字转移到当前,所以说如果把 \(i\) 相同的数字按 \(j\) 从大到小排序,对于这些 \(i\) 相同的数里面,前面的数,\(j\) 都比当前的 \(j\) 大,就成功的避免了这种情况。
时间复杂度 \(O(nlogn)\) ,就是求 \(LIS\) 的时间,可以二分求,可以权值线段树优化 \(DP\) 求。
\(C\) 题 \(Row\) \(Column\) \(Sums\)
有一个 \(n\) 行 \(m\) 列的矩阵,可以在其中的每个格子填 \([0,k-1]\) 中的数,给定 \(A,B\) 两个数列,要使得:
第 \(i\) 行的数字之和模 \(k\) 为 \(A_i\) 。
第 \(i\) 列的数字之和模 \(k\) 为 \(B_i\) 。
求合法矩阵中数字之和的最大值,若不存在,输出 \(-1\) 。
\(1 \le n,m,k\le 200000\)
难度评分 \(1583\) ,比较巧妙的贪心题,首先注意到求数字和的最大值,那么一类常用的思考方向是,考虑在所有格子都填上最大的数 \(k-1\) ,然后再来尽可能少地减去一些数使得条件成立。
独立地统计每一行,每一列需要减少的值,由于是模意义下,所以求出的值是最小的需要减少的值,设行上需要减少的值之和为 \(s1\) ,列为 \(s2\) ,那么具体的操作方案是,若 \(s1<s2\) ,在对每一列进行减少时,减少的位置是当前列需要减少的那些行的位置,如果当前列没有行可以继续减少了,那么不妨从当前列的第一行进行减少,这样我们保证了列的正确性,再看行,因为二者减少后,行之和与列之和模意义下必然相等,否则就是无解,而在有解的情况下,第一行那些被迫减少的只会让第一行进入下一个模数周期,也保证了正确性。
复杂度是 \(O(n+m)\) 的。

浙公网安备 33010602011771号