AT 题目讲解
cy 让我讲的,必须得要有一个博客啊。
写代码?那是绝对不可以的。
[ABC194E] Mex Min
Subtask 1
暴力都会吧。
枚举以 \(i\) 开头的长度为 \(m\) 的子序列,然后 \(i \sim i + m - 1\) 扫一遍,用一个桶记录一遍,即可求出 \(\text{mex}\) 值。
时间复杂度:\(O(n^2)\)。
Subtask 2
注意:仅限个人思路(口胡),可能不太正确。
考虑 \(\text{mex}\) 的本质是什么,是第一段连续区间的最大值 $ + 1$( \([-1, -1]\) 也算单独一段),所以我们考虑把他们维护一个差值,然后用线段树维护一下就行(维护连续为 \(1\) 的段,注意要特判不从 \(0\) 开始的)。
注意这种做法只有再 \(a\) 是有序的情况下才能做到以下复杂度。
时间复杂度:\(O(n \log_2 n)\)。
感觉卡卡能过去。
Subtask 3
开始牛逼的正解。
答:是我最不擅长的单调队列。
我们考虑维护一个单调队列(其实不是原汁原味的),或者说是维护一段长度为 \(m\) 的区间,考虑删除一个数,再加进来一个数,能否产生变化。
时间复杂度:\(O(n)\)。
Subtask 4
如果感觉自己很牛逼的可以进来看一看:
考虑可以回滚莫队去做。由于莫队 \(\text{mex}\) 只支持删除更新,所以我们使用回滚莫队,让它只删除(你会发现根本跑不满)。
时间复杂度:\(O(n \sqrt n)\)。
然后下面还介绍一种思路:
线段树上二分。
[ABC195D] Shipping Center
贪心题吗,就是乱贪。
Subtask 1
最原始的暴力算法。
直接爆搜箱子全排列把的箱子给这 \(n\) 个人匹配。
时间复杂度:\(O(?)\)。
Subtask 2
有没有一种感觉,这个题像 DP。
考虑状压:
设 \(f_{i, j}\) 为行李使用状况的集合和盒子使用状况的集合(\(1\) 表示用过,\(0\) 表示没用过),然后你暴力枚举之前是用得哪一个盒子和哪一个行李就 OK 了。注意到 \(i\) 和 \(j\) 二进制里 \(1\) 的个数应该是相等的,所以可以优化避免冗余状态。
时间复杂度:\(O(2^n 2^m n m)\)。
也就比爆搜快了一点而已。
Subtask 3
有一句古话是这么说的:你往往没有思路的题都是贪心。
所以我们贪心。
考虑最小的盒子一定要装尽量大的价值,考虑感性证明:
尽量小的盒子如果装尽量大的价值,那么必然之后就会多出一个物品的贡献(因为如果不用小盒子装肯定是用大盒子装),肯定是不劣的。
然后我们把价值从大到小排序,盒子容量从小到大排序,就 OK 了。
然后一个一个物品用盒子去匹配就好了。
时间复杂度:\(O(qn \log_2 n)\)。
[ABC204D] Cooking
Subtask 1
真没想到什么暴力,如果有暴力,可以提出来。
考虑最终答案是什么:
其实就是两个烤箱中消耗时间最长的那一个烤箱的时间。
所以这道题的目标是让我们让时间最小的那个烤箱时间尽可能长(因为时长是固定的,要做到尽可能平均),所以我们可以设 DP 状态 \(f_{i}\) 表示在不超过这么多时间内,做菜时间最长是多少。
然后由于每个菜只有一道,就可以 01 背包去搞了。其实上面那个状态是滚动数组优化过的。
[ABC205D] Kth Excluded
Subtask 1
直接枚举就行了。复杂度直接升天。
Subtask 2
不难发现这道题的 \(a\) 是有序的,所以我们可以往单调性这一块方面想(其实出现第 \(k\) 小这种字眼都可以往单调性去想)。
又是第 \(k\) 小,所以不难想到可以二分去做。
我们定义 \(f_i\) 为 \(1 \sim i\) 不同于 \(a_i\) 正整数个数,不难发现这个数组是单调不减的。
考虑 \(f_i = i - g_i\),\(g_i\) 为 \(a\) 数组中不超过 \(i\) 的数有多少个,可以 \(\text{map}\) + 前缀和(二分是最好的)去搞(当然你用动态开点权值线段树我也没意见)。
时间复杂度:好一点是 \(O(n + \log_2 10^{18})\),不好就是 \(\log_2^2\) 了,其实没多大差别。