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\)了啊,怎么也想不到。。。