题目
https://gmoj.net/senior/#main/show/6854
题目大意
给你一个长度为 n n n的序列 s s s和 m m m个询问,每个询问会给出两个正整数 l , r ( 1 ≤ l ≤ r ≤ n ) l,r(1\le l\le r\le n) l,r(1≤l≤r≤n),求 ∑ i = l r ∑ j = l r ( max k = i j s k ) ⋅ ( min k = i j s k ) \sum_{i=l}^r \sum_{j=l}^r \left(\max_{k=i}^j s_k\right) \cdot \left(\min_{k=i}^j s_k\right) i=l∑rj=l∑r(k=imaxjsk)⋅(k=iminjsk)
题解
看到这个套娃的询问就觉得很烦,但因为这是模拟赛中为数不多的数据结构题,让我想要一试。
解法1
这是我考场上的思路。
考虑枚举询问区间的右端点(即 r r r),那么以这个点的答案等于 r − 1 r-1 r−1的答案加上以 r r r为上式中的 j j j的答案。
由于现在固定了区间的右端点,因此很容易想到在左端点上放答案。每个左端点上的答案由它到右端点的 m a x , m i n max,min max,min决定,这个要在线维护,可以考虑用单调栈。那么现在还需要一个支持区间修改、区间查询的数据结构,那就用线段树吧!
可以发现每一次将所有区间都修改一下是不现实的,由于很多修改都是重复的,只要 m a x , m i n max,min max,min不变,修改量不变。因此打上时间戳就可以处理了。
但是这样做要在线段树上维护很多值,而且细节很多,就没有实现了(考场上也没有打出来)。
解法2
题解神奇分治算法。
将整个 [ 1 , n ] [1,n] [1,n]的区间分治一下,对于每个区间只维护跨过 m i d mid mid的区间 [ i ,