传送门
设
f
(
x
)
=
x
(
x
+
1
)
2
f(x)=\frac{x(x+1)}2
f(x)=2x(x+1)
考虑矩形的左边界和有边界的位置,如果在同一个
s
e
c
t
i
o
n
section
section以内的话,答案即为
f
(
w
)
f
(
h
)
f(w)f(h)
f(w)f(h)。
否则答案为 ∑ 1 ≤ i < j ≤ n w i w j f ( m i n i ≤ k ≤ j { h k } ) \sum_{1\le i<j\le n}w_iw_jf(min_{i\le k\le j}\{h_k\}) ∑1≤i<j≤nwiwjf(mini≤k≤j{hk}),我们可以枚举右端点,然后固定右端点为 r r r,通过单调栈维护 ∑ i = 1 r − 1 w i f ( m i n i ≤ k ≤ r { h k } ) \sum_{i=1}^{r-1}w_if(min_{i\le k\le r}\{h_k\}) ∑i=1r−1wif(mini≤k≤r{hk})的值,因为从 i i i到 r r r的最小 h h h只会随着 r r r的增大越来越小,因此维护一个单调递增的栈即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int mod = 1e9+7;
int w[maxn],h[maxn];
struct Node{
int v,h;
}st[maxn];
int f(int x){
return (1ll*x*(x+1)>>1ll)%mod;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&h[i]);
int ans=0;
for(int i=1;i<=n;++i){
scanf("%d",&w[i]);
ans=(ans+1ll*f(w[i])*f(h[i])%mod)%mod;
}
int top=0,sum=0;
for(int i=1;i<=n;++i){
int vv=w[i]%mod;
while(top && st[top].h>=h[i]){
vv=(vv+st[top].v)%mod;
sum=(sum-1ll*st[top].v*f(st[top].h)%mod)%mod;
top--;
}
st[++top]=Node{vv,h[i]};
sum=(sum+1ll*vv*f(h[i])%mod)%mod;
ans=(ans+1ll*(sum-1ll*f(h[i])*w[i]%mod)*w[i]%mod)%mod;
}
ans=(ans+mod)%mod;
printf("%d\n",ans);
}