【Codeforces 1120A】Diana and Liana

Codeforces 1120 A

题意:给\(n\)个数\(a_1..a_n\),要从其中删去小于等于\(n-m\times k\)个数,使得将这个数组分成\(k\)个一段的序列时有至少一段满足以下条件:设这\(k\)个数为\(c_1..c_k\),其中必须含有\(b_1..b_s\)这\(s\)个数(如果有重复得数量比\(b\)中的还多)。

问任意一种方案。

思路:我的思路比较鬼畜。。。

首先我们考虑满足要求的这\(k\)个数从\(i\)号位置开始后的情况。

首先我们需要看\(b\)中的每个数在\(a\)中出现的每一个位置,以便求出这个东西:

从\(i\)开始找\(cnt_{b_j}\)个\(b_j\)达到的最后一个\(a_l\)的最大下标\(l\)。

然后这玩意可以(明显的)通过维护现在到了对于所有的\(j\),\(b_j\)的第几次出现来在\(O(1)\)时间内求出。

再判断一下将\(i\)之前的数删除到\(i\)保持在一个\(k-\)段的开头的代价加上将\(k-\)段中间的内容删除以至于满足的数们可以放在同一个\(k-\)段中的代价是否超过了\(n-m\times k\)。如果没超过就输出答案。

然后这个方案的输出折腾了我半天。。。我们应该将所有\(i\)之前的使得\(i\)不是\(k\)的开头的\(j\)都给他删掉,并且把\(i\)之后的不是\(k-\)段之内的也给删掉。

Codeforces 1120 A 分析

Markellonchik、chemthan、LHiC、Atreus、aid、yzyyylx、Barichek、nicklu0、stO、HwSh、teja349、Fekete、Rzepa、JustasK、Arturgo、huzzah:

使用\(two\ pointers\)来求出对于每一个\(l\),最早的使\([l,r]\)中包含\(b_{1..s}\)成立的\(r​\)。

然后如果需要删掉的最少的数的个数满足要求,那么就输出方案。

mango_lassi、archie_fake、al13n:

对于每一个\(i\),看\([i-(n-(m-1)*k)+1,i]\)这一段区间(取能够取的最多的数)中每一个数有多少个,是否满足大于等于在\(b\)中出现次数的要求,如果满足那么就输出方案。用滑动窗口的办法来解决每一个数多少个的问题。

step_by_step:

和我的做法类似。

总结:大多数人都用的是\(two\ pointers\)???我还是太\(naive\)了啊,怎么也想不到。。。

上一篇:php php-5.6.4.tar.bz2 apache 兼容问题 child pid 27858 exit signal Segmentation fault


下一篇:tar 解压bz2报错 Cannot exec: No such file or directory