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)\) 的。

posted @ 2022-01-23 12:05  Constant1227  阅读(157)  评论(1)    收藏  举报