真是个码农题……
由于是乘,所以没法用单调栈来统计答案贡献。
考虑分治套路,于是问题变成了求区间左端点 ∈[l,mid],区间右端点 ∈[mid+1,r] 的答案。
由于最值的单调性,我们可以多维护两个指针使得每层递归只需 O(n)。
具体地说,我们按 mid→l 顺序枚举 i,并同时维护满足 j1maxj=mid+1aj≤midmaxj=iaj 的最大的 j1 和满足 j2minj=mid+1aj≥midminj=iaj 的最大的 j2。
于是我们就可以把计算 [mid+1,r] 对 i 的贡献分成三个部分,这里我们假设 j1<j2,反过来类似: 1. [mid+1,j1],这一段的最值与 [i,mid] 相同。 2. [j1+1,j2],这一段仅最小值与 [i,mid] 相同。 3. [j2+1,r] 这一段的最值与 [i,mid] 不同。
于是我们可以在递归进入时维护五个量: 1. maxi=imaxj=mid+1aj 2. mini=iminj=mid+1aj 3. maxsumi=i∑j=mid+1maxj 4. minsumi=i∑j=mid+1minj 5. sumi=i∑j=mid+1maxi⋅mini
通过这五个量,三个部分的贡献就容易得出了。
此外,注意取模时,应该把较大的数先取模再乘。
代码:
1 |
|