Codeforces Round 1022 (Div. 2) 题解及证明

Codeforces Round 1022 (Div. 2) 题解及证明

主播很菜,四题退场,还不会 e

现在只有 ABCD 题解

声明:所有区间左闭右开,数组编号 \([0, N)\)

A. Permutation Warm-Up

难度(个人感觉):\(\star\star\)(放在 a 题思维难度偏大)

看起来非常困难。
拆解一下,

\(\sum_{i=1}^N |a[i] - i|\)

一定有 N 个数取正号,N 个数取负号。

哪些值可取呢?

结论:一定是偶数,而所有不超过最大值(马上会给出)的偶数都可取

  1. 先决定数的符号,每种数有两个,先分别把一个取负号,此时为和为 0。不断将某个负号移到小 1 的数会导致和 sum += 2,每次可以通过 括号序列的方式 匹配,最终和会变为最大值。

    以 N = 4 为例

  2. 还要还原到原数组上,我们将匹配的数连边,每个数度数为 2,所以我们的方案会形成一些环,然后把每个环变成有向的,构造 a 使得如果 u -> v,那么让 \(a[u] = v\)

总之,0 到 最大值之间的偶数都是可取的,其中最大值即 2N 个数中,最小的 N 个取负号,即 \(max = \sum_{i=1}^N |(N + 1 - i) - i|\),答案是 \(max / 2 + 1\)

B. SUMdamental Decomposition

难度(个人感觉):\(\star\star\)(需要分类讨论)

分类讨论 WA 了一发

总体思路是先把每个二进制位分给每个数,如果数多了就给他们分配 1 来抵消

记 p 为 popcount(x), p[i] 为 popcount(a[i]$);

  1. \(n \le p\) 答案就是 \(x\)。这当然最优。

  2. 否则如果 \(n - p\) 是偶数,答案就是 \(x + n - p\),因为 \(\sum_{i=0}^{N-1} p[i] \ge x + n - p\)(前者给出 p 个,后者给出 N - p 个),

  3. 否则如果 \(n - p\) 是奇数,

    • 2.1 如果 \(x \ge 2\)

      那么先从小到大从前往后放 \(x\) 的二进制位,然后从后往前加入 1 即可。

      比如 \(n = 6, x = 13\)

      从小往大从前往后加入二进制位:

      1 4 8

      从后往前加入 1

      1 4 (8+1) 1 1 1

      答案是 \(x + ceil((n - p) / 2) * 2\)。这是最优的,因为 \(\sum_{i=0}^{N-1} p[i] \ge x + ceil((n - p) / 2) * 2\)(因为要求后者异或和为 0),

    • 2.2 如果 \(x = 1\)

      此时 \(p = 1, n\) 是偶数。我们需要让两个东西当一个1,其中最优的是 \(2 \oplus 3 = 1\)。 所以答案是 \((n - 2) + 2 + 3\)。这样做最优的原因是

      不可能只多 1

      (\(1 \oplus 1 \oplus ... \oplus 1 \oplus 2\) = 3)

      或者多 2。

      (\(1 \oplus 1 \oplus ... \oplus 1 \oplus 2\oplus 2\) = 3)

      (\(1 \oplus 1 \oplus ... \oplus 1 \oplus 3\) = 3)

    • 2.3 \(x = 0\)

      此时 \(p = 0, n\) 是奇数。n > 1 时答案是 \((n - 2) + 2 + 3\)

      不可能只多 1

      (\(1 \oplus 1 \oplus ... \oplus 1 \oplus 2\) = 2)

      或者多 2。

      (\(1 \oplus 1 \oplus ... \oplus 1 \oplus 2\oplus 2\) = 1)

      (\(1 \oplus 1 \oplus ... \oplus 1 \oplus 3\) = 3)

      特别的,\(n = 1\) 时无解。因为我们的替换方案至少要两个数。

C. Neo's Escape

难度(个人感觉):\(\star\star\)(思维难度适中)

结论:一种划分可行 当且仅当 每个 clone 能的管理一个 升-降(即先增后减) 的区间(这里升/降 的次数可以为 0),如 1 1 1,1 2 4,1 4 5 3 2。

证明:

\(\Leftarrow\), 即 升-将 划分都可行:将数组划分成先一些 升-降 区间,clone 按在其管理的区间的最大值处。每次找到数组中未访问最大的点,让管理它的 clone 移过去。如果这个点就是区间最大值,那么肯定没问题。否者由于上一个点更大,移动过程中一定不会访问更小点(否则存在 严格降-升 区间,但 升-降 区间中不存在这样的子区间),矛盾

\(\Rightarrow\),即 可行划分都是 升-将 划分:由于先访问大的再访问小的,相对起点同侧(即分别讨论起点左边的,起点右边的),靠近起点的一定先访问所以必须更大,也就是两侧都是相对起点(不严格)递降,即整个管理区域 升-降 区间

具体写法有两种,一种是直接遍历,\(d = 0\) 表示处于 升,\(d = 1\) 表示处于降

void solve(){
  ans = 1;
  bool d = 0;
  for(int i = 1; i < N; i++){
    if(d == 0 && !(a[i - 1] <= a[i])){
      d = 1;
    } else if(d == 1 && !(a[i - 1] >= a[i])){
      ans++;
      d = 0;
    }
  }
}

另一种写法是统计峰的个数

峰指先去重后,将第一个数之前,最后一个数之后安排极小值后, i 使得 \(a[i - 1] < a[i] < a[i + 1]\) 。容易说明每个峰管理一个区间,并且合起来就是整个区间。

void solve(){
  ans = 0;
  a.erase(std::unique(a.begin(), a.end()), a.end());
  for(int i = 1; i + 1 < a.size(); i++){
    ans += a[i - 1] < a[i] && a[i] > a[i + 1]; 
  }
}

D. Needle in a Numstack

难度(个人感觉):\(\star\star\star\)(思维难度简单但范雷讨论很复杂)

思路是

  1. 分别找出 %k 的表 (=\(2k\) 次)

    for(int i = 0; i < k; i++){
      a[i % k] = query(i);
    }
    for(int i = N - k; i < N; i++){
      b[i % k] = query(i);
    }
    

    如果 a 和 b 完全相同,那么 \(N = 2k\) 时分别是 \([0, k)\), \([k, N)\),否则不可判定。

    不然就继续往下做

  2. 找到任意一个 a 和 b 中不同的 %k 的位,记作 diff。

  3. 二分出 a 中的 i 使得 \(i \% k == diff \; and \; C[i] == b[diff]\),记作 pos (\(\le ceil(log2(V=N/k)) \le 20\) 次)

  4. 往前走,找到第一个 i 使得 \(a[i] \% k != C[i] \; and \; b[i] \% k == C[i]\),记作 first 。(\(=k\) 次)

    这个位置在 \((pos - k, pos]\) 之间,否则这个值后面第一个 \(\%k == diff\) 的位 i 比 pos 小但由于前面有个东西在 B 中,这个东西也一定在 B 中, \(C[i] == b[diff]\)\(a[diff] != b[diff]\),与 pos 是最小的那个矛盾。

  5. 判断有没有可能相同(这个很复杂)

    如果 \(first = k\), 前面一个数组一定只有 \(k\) 个数,即 \([0, k), [k, N)\)

    如果 \(first > N - k\), 后一个数组的开头一定在 \(N - k\) 及以前。如果第 \(N - k - 1\) 位有可能属于 a 也有可能属于 b,即 \(a[(N - k - 1) \% k] = b[(N - k - 1) \% k]\) 那么 \([0, N - k), [N - k, N)\)\([0, N - k - 1), [N - k - 1, N)\) 都可行,输出 -1,否则分别是 \([0, N - k), [N - k, N)\)

    否则 \(k < first <= N - k\),取 \([0, first), [first, N)\) 显然可行。如果第 \(first - 1\) 位有可能属于 a 也有可能是属于 b,即 \(a[(first) \% k] = b[(N - k - 1) \% k]\) 那么输出 -1,否则是唯一的。

总计 \(\le 170\)

posted @ 2025-05-02 00:44  陈聂  阅读(669)  评论(3)    收藏  举报