5807. 【NOIP提高A组模拟2018.8.13】简单的区间(在线分治(树上启发式合并 或 分治中心) 或 离线分治(主席树或桶))

5807. 【NOIP提高A组模拟2018.8.13】简单的区间

Problem

5807. 【NOIP提高A组模拟2018.8.13】简单的区间(在线分治(树上启发式合并 或 分治中心) 或 离线分治(主席树或桶))_第1张图片

  • n3105,k106 n ≤ 3 ∗ 10 5 , k ≤ 10 6
Solution
  • 首先考虑分治.

  • 对于一个区间 [l,r] [ l , r ] ,我们考虑其中最大的数位置在 m m ,那么区间可以被分成两段, [l,m],[m+1r] [ l , m ] , [ m + 1 , r ]

  • 那么这个时候考虑枚举小的那一段的位置,大的那一段可以离线处理,具体的,我们可以把问题转化为在大的那一段中查找某个数出现次数.

  • 如何转化,其实就是前缀和的加减操作.

  • 然后离线,可以考虑用主席树解决,当然,这样做是 O(nlog22n) O ( n l o g 2 2 n ) 的.

  • 于是可以考虑用一个桶来储存,对于一个询问 [l,r] [ l , r ] ,在 [l1],[r] [ l − 1 ] , [ r ] 两个位置打标记,差分即为答案。

  • 如何在线呢?可以考虑树上启发式合并。

  • 我们储存两个桶,分别表示前缀和,后缀和.

  • 每次递归的时候可以考虑先走小的那一边,然后更新桶.

  • 往右边走的时候把桶清空,注意,往右边走之后桶不要清空,然后最后再把左边的桶加回去,再返回,那么每次就可以处理出大区间那一边的桶。

  • 且显然这样做是 O(nlog2n) O ( n l o g 2 n ) 的.

  • 那么还有一种在线分治的算法,我们可以不用找区间最大的那个数.

  • 直接找到分治中心,然后可以从中心往一边走,维护一个最大值,以及位置,对应的一边可以找到某一个位置,那么这一段就可以直接更新。

  • 然后这样要做两遍.

  • 因为是分治中心,所以每次减半,层数是 log l o g 的,总时间复杂度也是 O(nlog2n) O ( n l o g 2 n ) .

  • 只不过这种做法打起来要稍微复杂点,因为要处理最大值相同的情况, 其实也不难,可以规定一边计算,另一边不算即可.

你可能感兴趣的:(5807. 【NOIP提高A组模拟2018.8.13】简单的区间(在线分治(树上启发式合并 或 分治中心) 或 离线分治(主席树或桶)))