[ABC365G] AtCoder Office 题解

一道根号分治的典题。

因为 polylog 不好做(没有有效的数据结构维护许多个一组的区间并),故考虑根号算法。
指定一个分割点 \(B\),我们把在记录中出现次数大于等于 \(B\) 次的人称为【大人】,出现次数小于 \(B\) 次的人称为【小人】。
现在询问分为两种。

  • 【小人】和【小人】询问。
  • 包含【大人】的询问。

先处理第二种,包含【大人】的询问。【大人】的个数不超过 \(O(\frac{m}{B})\) 个,从这里入手。
我们预处理出每个【大人】与所有其他人之间的询问。基本的思路就是:

  • 枚举【大人】\(i\)
  • 枚举其他任意一个人 \(j\)
  • 枚举 \(j\) 的所有进出区间(显然可能有多个),对于每个单区间求出其与 \(i\) 的所有区间的交的大小。

由于区间个数总和是 \(O(n+m)\) 的,故这样做是 \(O(\frac{nm+m^2}{B})\) 的。
那只剩一个问题:如何快速求一个【大人】和一个单区间的交?

我们将时间离散化,记 \(sum_{i,j}\) 为第 \(i\) 个【大人】,从 \(0\) 到离散化后的时间 \(j\) 的范围内,【大人】在办公室内多久。
这本质是个前缀和,可以在 \(O(\frac{m^2}{B})\) 的时间复杂度内求出。
于是我们对于【大人】\(i\) 和一个单区间 \([l,r]\)(离散化后),答案就是 \(sum_{i, r} - sum_{i, l}\)。这个过程不会出现 \(r\)\(l\))在【大人】的某一个区间内,而【切断】了 \(sum\) 数组,因为 \(sum\) 在计算的时候就将所有离散化后的时间都考虑到了。

于是,【大人】\(i\) 和任意人 \(j\) 的答案 \(f_{i,j}\) 就是 \(\sum_{[l, r] \in all \ ranges \ of \ j} sum_{i,r} - sum_{i, l-1}\)。统计答案的过程可以在 \(O(\frac{nm+m^2}{B})\) 的时间复杂度内求出。


再看小人和小人之间的询问。这个直接用类似双指针的思想做,可以在 \(O(B)\) 的时间复杂度内解决,全部询问时间复杂度为 \(O(qB)\)。(但是 \(O(B^2)\) 的暴力反而快 \(2\)

\(B\)\(\sqrt m\),理论时间复杂度最优,为 \(O((n+m+q)\sqrt m)\)

submission.

posted @ 2025-02-14 23:06  Water_M  阅读(23)  评论(0)    收藏  举报