如果你使用电脑查看这个页面,可以使用 CTRL + SHIFT + L 启用深色模式.

A - 369

等差数列的两个数字固定之后,第三个数字只有三种可能:$2a - b, 2b - a, \dfrac {a+b} 2$. 直接算出数字去重或者使用数学方法均可.

时间复杂度 $O(1)$.

int main() {
  int a, b; cin >> a >> b;
  if (a == b)
    puts("1");
  else
    printf("%d", 2 + ((a + b) % 2 == 0));
  return 0;
}

B - Piano 3

为了使得失败率尽可能低,显然每次直接移动到目标位置是最优的. 按照这个策略维护左右手所在的位置即可.

时间复杂度 $O(n)$.

int main() {
  int n; cin >> n;
  int L = -1, R = -1, ans = 0;
  for (auto [a, b]: getv<int, char>(n)) {
    if (b == 'L') {
      if (L != -1)
        ans += abs(L - a);
      L = a;
    }
    else {
      if (R != -1)
        ans += abs(R - a);
      R = a;
    }
  }
  printf("%d\\n", ans);
  return 0;
}

C - Count Arithmetic Subarrays

一个数组形成等差数列,当且仅当差数组相同. 在额外计算长度为 1 的数组后,将原数组差分,然后通过双指针获得数字相同的段,根据基本组合知识即可得到答案.

时间复杂度 $O(n)$.

int main() {
  int n; cin >> n;
  auto a = getv(n);
  for (int i = 1; i < n; i ++)
    a[i - 1] -= a[i];
  i64 ans = n;
  a[n - 1] = 1e9 + 10;
  for (int i = 0, j; i < n - 1; i = j + 1) {
    j = i;
    while (a[j + 1] == a[i])
      ++ j;
    ans += 1ll * (j - i + 2) * (j - i + 1) / 2;
  }
  printf("%lld\\n", ans);
  return 0;
}

D - Bonus EXP

设 $f_i$ 和 $g_i$ 分别表示考虑前 $i$ 个怪物,分别在打败奇数个怪物和偶数个怪物的前提下可以获得的最大经验值. 考虑当前怪物是否打败,即可得到简单的转移方程. 进一步的,因为当前状态只和上一个怪物的状态有关,所以可以将 $f$ 和 $g$ 数组改成两个值. 具体表达式参见代码.

时间复杂度 $O(n)$.

int main() {
  int n; cin >> n;
  auto a = getv(n);
  i64 A = 0, B = -1e18;
  for (auto e: a)
    tie(A, B) = tuple{
      max(A, B + 2 * e),
      max(B, A + e)
    };
  printf("%lld", max(A, B));
  return 0;
}

E - Sightseeing Tour

注意:直接使用 Dijkstra 算法在分层图上跑最短路会 TLE.

考虑到 $n$ 并不大,而 $m$ 可能很大,故可以考虑先用 Floyd 算法计算出两个点之间的最短距离.