Codeforces Round #690 (Div. 3) 题解(A-F)

AC代码

A. Favorite Sequence

搞两个指针分别指向头尾,然后模拟每次往内移动,依次读取指针指向的元素。

B. Last Year's Substring

枚举头部匹配几个字符,剩下的就只用尾部匹配,模拟一下完事。

C. Unique Number

贪心,从个位数开始优先使用值大的数,模拟一下完事。

D. Add to Neighbour and Remove

如果最后能够得到长度为\(m\),且所含元素都相等的数组,那么就可以通过\(n - m\)次操作满足题意。

结果数组中,第1个元素必定是原数组的一段前缀合并得到的。

假设结果数组中第1个元素是原数组中前\(i\)个元素合并得到,由于目标值已经确定了,所以只需要一遍循环就可以判断剩下的元素是否可以通过相邻合并得到多个目标值且没有剩余。

枚举\(i\),每次\(O(n)\)判断是否符合条件,若符合就更新答案。时间复杂度为\(O(n^2)\)

E2. Close Tuples (hard version)

通过\(O(n)\)前缀和预处理就可以\(O(1)\)得到数值位于\([l, r]\)之间的元素个数\(f(l, r)\)

枚举最小值\(mi\),最小值\(mi\)确定,最大值\(ma\)也就可以确定为\(min(mi + k, n)\)

然后以\(mi\)为最小值的元组数\(d_{mi} = C(f(mi, ma), m) - C(f(mi + 1, ma), m)\)。其中\(C(n, m)\)表示\(n\)个元素选\(m\)个元素的方案数。

而答案就等于\(\sum_i^n d_i\)

F. The Treasure of The Segments

枚举作为和集和中所有线段都有交集的线段,记为\([l, r]\)。那么需要删去的线段就是满足右端点小于\(l\)或者左端点大于\(r\)的线段。

如果对端点进行离散化,然后用一个树状数组\(L\)记录左端点位于\(i\)的线段个数,再用一个树状数组\(R\)记录所有位于右端点位于\(i\)的线段个数,那么就可通过树状数组的前缀和以及后缀和查询,在\(O(\log n)\)内计算出对于单个线段需要删去的线段个数。再枚举每一个线段,答案取最小值,就可以在\(O(n \log n)\)的时间解决本题。

其实没有必要用树状数组,因为并没有更新操作,所以\(O(n)\)预处理下前缀和就可以了,这样总体时间复杂度为\(O(n)\)

posted @ 2020-12-16 00:47  _Backl1ght  阅读(100)  评论(0编辑  收藏  举报