第十分块。
看到题第一反应肯定是想把询问按 x 排序。
但是有修改。
假设能较快地支持一次修改,那么如果直接暴力类似带修莫队在上一次询问的基础上转移的话,复杂度是 O(m2) 的。
这启发我们什么?
莫队。
然而,虽然它是标算,但我还不会(
所以把操作分块。每 O(√m) 个操作处理一次。
于是现在需要支持较快地修改。
假如没有额外的修改操作,我们需要支持的就是维护一个 01 序列,支持把 0 变成 1,询问区间内所有极长 1 的连续段的子区间个数之和。
考虑分块。
这个分块相对比较简单:只需要考虑维护所有块内的极长连续段,在左端点处记录右端点,右端点处记录左端点,并记录块内的答案。
这里为了便于区间询问,记录块内答案时不记录在块的边界上的连续段的贡献。
然后区间询问就是一个经典 PJ 操作。
这个分块不难实现 O(1) 修改 O(√n) 询问,而同时也应当注意到我们的修改次数大致是 O(m√m),所以这里达成了一种平衡。
下一个问题:额外的修改可能把 1 变成 0,怎么办呢?
注意到最多只有 O(√m) 次本质不同的额外的修改,然后又发现这个分块容易支持撤销上一次操作。
于是可以得到这样一个想法:在一般地按照权值把 0 变成 1 的过程中,不考虑被修改的位置;在处理询问时暴力判断每个被修改的位置是否需要变为 1,回答询问后撤回。
这样就可以了。
时间复杂度 O(n√n),视 n,m 同阶(其实是懒得算了吧)。
然而卡常力度略微有点大。
感谢松式基排,它实在是太香了!
代码:
1 |
|