[ARC130E] Increasing Minimumm

发布时间 2023-10-10 21:32:26作者: DCH233

[ARC130E] Increasing Minimumm

考虑模拟一下题目中的过程,发现相当于将原序列按照初始值划分为若干个等价类,然后每次都会先合并等价类然后重排等价类中的所有数并加入 \(I\) 中。这样将 \(I\) 划分成了若干段。

考虑假设我们一共划分出 \(T\) 个段,那么最终每个数的答案就是 \(T\) 减去 \(i\) 出现的次数,当然最终我们假设每个数都至少出现了一次,如果某些数没出现过就假装它出现过。

然后发现只需贪心地让划分的总段数最小并且最后一段最大即可。有一个贪心的想法是尽可能长的划分每一段,可惜无解判错了,直接上个 dp 就做完了。

复杂度 \(O(N + K)\)

int main() {
  read(n, k);
  for(int i = 1; i <= k; ++i)
    read(a[i]), ++cnt[a[i]];
  int pre = 0;
  for(int i = 1, tot = 0; i <= k; ++i) {
    pre = max(pre, lst[a[i]]);
    if(!lst[a[i]]) ++ tot;
    lst[a[i]] = i;
    if(pre == i - tot) f[i] = f[pre] + 1;
    else f[i] = inf;
  }
  f[k + 1] = inf;
  int pos = k + 1;
  for(int i = pre; i <= k; ++i)
    if(f[i] <= f[pos])
      pos = i;
  if(f[pos] == inf) {
    puts("-1");
    return 0;
  }
  for(int i = pos + 1; i <= k; ++i)
    vis[a[i]] = 1;
  for(int i = 1; i <= n; ++i)
    printf("%d ",cnt[i] ? f[pos] - cnt[i] + vis[i] + 1 : f[pos] + 1);
  puts("");
}