AtCoder Beginner Contest 233


A,B,C 略过。

D

求有多少个二元组 \((l,r)\) 满足 \(\displaystyle \sum_{i=l}^{r} A_i=K\)

先求出前缀和,记为 \(s_i\),那么要求就是 \(s_r-s_{l-1}=K\),移项一下 \(s_{l-1}=s_r-K\),那么考虑统计 \(s_r-K\) 的数量,最后将所有 \(l\) 加起来。

代码

E

\(\displaystyle \sum_{k=0}^\infin \lfloor \dfrac{X}{10^k} \rfloor\) 的值。

列竖式模拟一下,发现相当于每次向左移动一位,然后加起来,最后往上进位。

然后求不进位的值的时候,每一位都是前缀和。

代码

F

给定一个长度为 \(n\) 的排列 \(P\),同时给出 \(m\) 个操作 \((a_i,b_i)\),可以把 \(P_{a_i}\)\(P_{b_i}\) 交换,判断是否能构造一组操作次数不超过 \(5 \times 10^5\) 步的操作序列使得 \(P\) 变为升序。

初看难以入手,直接的判断似乎很麻烦,那么考虑往图的方向想。

\(m\) 个操作可以抽象成一个图,那么如果 \(P_i\)\(i\) 不在同一个连通块,那么一定不能拍成升序,所以可以用并查集判断一下。

那么考虑构造方案,因为直接冒泡排序的次数是 \(999+998+\cdots +1=499500\),所以随便建出一个生成树,然后从度数为 \(1\) 的点开始交换并删点就好了。

代码

G

给定一个 \(n\times n\) 的网格图,有若干个格子有障碍。每次可以选择一个 \(d\times d\) 的区域然后消耗 \(d\) 点体力将其中的障碍消去。问将所有障碍消去的最小体力消耗。

考虑一个子问题 \(m\times n\) 的网格,那么消掉这里的障碍至多要 \(\max(m,n)\) 的体力,中间有可能会有空行或者空列,那么可以把这个网格沿着空行或者空列切开,转化成更小的子问题。

那么记 \(f_{i,j,k,l}\) 表示左上角 \((i,j)\) 右下角 \((k,l)\) 的最小消耗,记搜转移即可。

代码

Ex

平面上给定 \(n\) 个点,\(q\) 个询问,每次询问到点 \((x_i,y_i)\) 的第 \(k\) 近的曼哈顿距离。

\(1 \leq n \leq 10^5\)\(1 \leq q \leq 10^5\),时限 \(\texttt{7s}\)

口胡一下,曼哈顿距离的第 \(k\) 小难以解决,因为有绝对值,然后两个维度。

那么考虑一个小技巧,将每个点变成 \((x+y,x-y)\),这样曼哈顿距离就转化成切比雪夫距离。

于是每次询问我们二分答案,然后查询有多少点到询问点的距离小于等于二分的答案,这样就做一个查询矩形和,主席树维护一下。

代码不想写,咕了。