分治
新版题中还没有分治题解,而且旧版题里面分治也貌似是小众做法,那我来水一发吧。
不需要复杂的数据结构,你只需要会一个桶和基本分治套路。
因为 $P$ 是一个排列,所以连号区间等价于 $\max_{i=l}^rP_i-\min_{i=l}^{r}P_i=r-l$。
在解决这种限制条件中含有区间极值的全局区间计数问题时,分治非常有用。
考虑当前分治区间 $[L,R]$,设 $mid$ 为区间中点,把完全包含在 $[L,mid]$,和 $(mid,R]$ 的区间扔到下一层分治去计算。此时就只需要考虑左端点在 $[L,mid]$,右端点在 $(mid,R]$ 的区间了。
设一个需要考虑的区间为 $[l,r]$,设 $m=\max_{i=l}^r P_i$。
第一种情况:
$l,m\in[L,mid];r\in(mid,R]$。
转化等式,有 $\max_{i=l}^{r}P_i+l=\min_{i=l}^rP_i+r$。
考虑对每一个 $l$ 找出一个最大的 $r$ 满足 $\max_{i=mid+1}^r P_i < \max_{i=l}^{mid} P_i$。
这个时候就只需要考虑有多少个 $r’\in(mid,r]$ 满足$\min_{i=mid+1}^{r’}P_i+r=m+l$,开个桶记录一下就行,同时要注意去掉 ${r’‘|\min_{i=l}^{mid}P_i<\min_{i=mid+1}^{r’‘}P_i}$ 的贡献并判一下对应的 $r’‘’=\max_{i=l}^{mid}P_i+l-\min_{i=l}^{mid}P_i$ 是否在范围内。
第二种情况:
$l\in[L,mid];r,m\in(mid,R]$。
可以发现这两种情况加上分治下去处理的区间覆盖了所有区间。
转化等式,有 $\max_{i=l}^{r}P_i-r=\min_{i=l}^rP_i-l$。
处理方法跟上面类似,这里不再赘述。
code:
1 | #include<bits/stdc++.h> |
时间复杂度 $O(n\log n)$。

