注:本题解详细讲解了各部分分的得法以及对于正解的启发
问题转化
理解题意之后我们不难发现,只要我们能算出是否有以 i 块墙壁开始,刷 M 块墙的合法请求,那么这就转化成了一个区间覆盖问题。
比如: 样例1中,x=1,y=0 是一个合法请求,那么 [0,M-1] 就是一个合法区间(即:一次请求就可以覆盖这个区间)
找出这些区间之后,就可以做一个简单的贪心了,贪心代码如下:
|
|
预处理
但是,我们做完了吗?并没有。这题的不好搞的地方在于 canpaint 数组的预处理。
28分
NM^2 的暴力,枚举每个 x 和 y,并暴力匹配,能得到第二组和第三组的分数,代码过于简单,略。
51分
写一个dp,令 f[i][j] 表示从第 j 个商家,第i块墙壁开始匹配,最多能刷几块墙,则其转移如下
$$ f[i][j]=\left\{ \begin{aligned} &0&(第j个商家不能刷第i个墙)\\ &f[i+1][(j+1)mod M]&(第j个商家能刷第i个墙) \end{aligned} \right. $$但是 NM 的空间显然是存不下的,所以你需要将i那一维滚动掉,最终的时间复杂的也是 NM。
注:这里必须使用滚动数组,而不能使用其他方法,否则将无法保证后效性,因为这里的转移模了 M。
63分
观察数据特点:f(k)<1,我们可以利用这点来优化我们的dp,即:在转移时只转移喜欢 C[i] 这个颜色的那个商家即可,这个思路也给正解打下了基础,但至于加了这个优化之后,滚动时怎么清零之前计算的结果,待会会说。
100分
再看整体的数据范围,发现 f(k) 还是很小,所以我用一个 vector 数组 like[i] 表示喜欢第 i 种颜色的商家编号,转移如下:
$$ f[i][j]=f[i+1][(j+1)modM](j \in like[C[i]]) $$代码如下
|
|