跳转至

算法周赛round33

T1

已知 $a\leq b\leq c$,因此可以得到 $a\leq b\leq \ldots \leq a+b+c$。

因此得到前两个最小的数字,使用最大的数字减去前两个数字得和即可得到三个数字。


T2

如果可以访问农场 $i$ 则需要满足 $t_i+s<c_i$。移项可得 $s<c_i-t_i$。

定义序列 $a_i=c_i-t_i$,升序排序序列 $a$,当找到满足最小的 $j$ 使得 $s<a_j$ 依然成立。则 $a[j,n]$ 均可以被访问。

最小的 $j$ 可以使用 upper_bound 求出。判断是否有 $v$ 个农场即可。

时间复杂度:$O(n\log{n}+q\log{n})$。


T3

要使得序列的 mex = i,则序列中不能有 i。且 $0\sim i-1$ 的每个数字都必须存在(至少 $1$ 个)。

则对于每个 $i$,我们需要知道两个信息:

  • 序列中有几个 $i$,可以用计数数组统计。记 $i$ 的个数为 $x$。
  • 序列中 $[0,i-1]$ 有多少个数字不存在。记不存在的个数为 $y$。

则答案为 $\max(x,y)$。

$x$ 使用计数数组统计即可,$y$ 一边遍历一边维护即可。


T4

图象是关于中心点旋转对称的,因此首先一个位置 $(i,j)$ 其剩余三个对称点分别是:

  • $(i,n-j+1)$
  • $(n-i+1,j)$
  • $(n-i+1,n-j+1)$

那么修改一个位置 $(i,j)$ 的贡献,主要取决于这四个位置中哪一个字符占比最多。

int calc(int i, int j)
{
    int x1 = i, y1 = j;
    int x2 = i, y2 = n - j + 1;
    int x3 = n - i + 1, y3 = j;
    int x4 = n - i + 1, y4 = n - j + 1;
    int sum1 = 0;
    if (a[x1][y1] == '#')
        sum1++;
    if (a[x2][y2] == '#')
        sum1++;
    if (a[x3][y3] == '#')
        sum1++;
    if (a[x4][y4] == '#')
        sum1++;
    int sum2 = 4 - sum1;
    return min(sum1, sum2);
}

那么首先我们可以求出原本需要的最小操作数 res。即:

for (int i = 1; i <= n / 2; i++)
    for (int j = n / 2 + 1; j <= n; j++)
        res += calc(i, j);

对于每次修改的位置 $(i,j)$ 先令 $res \gets res-\texttt{calc}(i,j)$,减去这个位置的贡献。然后修改 $a_{i,j}$ 的字符以后,再令 $res \gets res+\texttt{calc}(i,j)$。

时间复杂度:$O(n^n+m)$。