Description
给定序列(a_i)
求
[sum_{i=1}^n sum_{j=i}^n (j-i+1)max{a_i,a_{i+1}cdots a_j}min{a_i,a_{i+1}cdots a_j}
]
Input
第1行,一个整数N;
第2~n+1行,每行一个整数表示序列a。
Output
输出答案对10^9取模后的结果。
Sample Input
4
2 4 1 4
Sample Output
109
【数据范围】
(N le 500000)
(1 le a_i le 10^8)
我还有什么话可以说呢,都是细节问题。细节什么的最讨厌了
维护前缀(sum1,sum2,sum3)分别是([0])里记录前缀中每一个数的(a_i*i)后的和,([1])里记录每一个数在区间里的前缀和,这样求一个区间的贡献可以表示成(sum[i][0]-sum[i][1]*j)
(j)是当前点的编号,于是这样玄学的复杂度>_<
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define ll long long
inline ll read(){
ll an=0;
char ch=getchar();
while(ch<'0'||ch>'9'){ch=getchar();}
while('0'<=ch&&ch<='9'){an=an*10+(ch^48);ch=getchar();}
return an;
}
const ll mod=1e9;
const ll MAXn=500000+2333;
ll ans;
ll n;
ll sum1[MAXn][2],sum2[MAXn][2],sum3[MAXn][3],a[MAXn];
/*
sum_{i=1}^nsum_{j=i}^n(j-i+1)
MAX{a_i,a_{i+1}cdots a_j}
MIN{a_i,a_{i+1}cdots a_j}
*/
inline void prepare(){
n=read();
for(ll i=1;i<=n;i++)a[i]=read();
}
inline void solve(ll l,ll r){
ll mid=l+r>>1;
if(l==r){
ans=(ans%mod+a[l]*a[l]%mod)%mod;
return;
}
sum1[mid][0]=sum1[mid][1]=0;
sum2[mid][0]=sum2[mid][1]=0;
sum3[mid][0]=sum3[mid][1]=0;
ll ma=-1,mi=1e9;
for(ll i=mid+1;i<=r;i++){
ma=max(ma,a[i]);
mi=min(mi,a[i]);
sum1[i][0]=ma%mod*mi%mod*i%mod;
sum1[i][1]=ma*mi%mod;
sum2[i][0]=mi*i%mod;sum2[i][1]=mi;
sum3[i][0]=ma*i%mod;sum3[i][1]=ma;
sum1[i][0]=(sum1[i][0]+sum1[i-1][0])%mod;
sum1[i][1]=(sum1[i][1]+sum1[i-1][1])%mod;
sum2[i][0]=(sum2[i][0]+sum2[i-1][0])%mod;
sum2[i][1]=(sum2[i][1]+sum2[i-1][1])%mod;
sum3[i][0]=(sum3[i][0]+sum3[i-1][0])%mod;
sum3[i][1]=(sum3[i][1]+sum3[i-1][1])%mod;
}
ma=-1,mi=1e9;
ll t1=a[mid+1],t2=a[mid+1];
ll p1=mid,p2=mid;
for(ll i=mid;i>=l;i--){
ma=max(ma,a[i]);
mi=min(a[i],mi);
while(t1>=mi&&p1<r)p1++,t1=min(t1,a[p1+1]);
while(t2<=ma&&p2<r)p2++,t2=max(t2,a[p2+1]);
ll tmp;
tmp=min(p1,p2);
ll wi=(mid+2-i+tmp-i+1)*(tmp-mid)/2;
ans=(ans+wi%mod*ma%mod*mi)%mod;
tmp=max(p1,p2)+1;
wi=sum1[r][0]-sum1[tmp-1][0];
wi=(wi-(sum1[r][1]-sum1[tmp-1][1])%mod*(i-1))%mod;
ans=(ans%mod+wi)%mod;
if(p1<=p2){
wi=(sum2[p2][0]-sum2[p1][0])%mod*ma%mod;
wi=(wi-(sum2[p2][1]-sum2[p1][1])%mod*(i-1)%mod*ma+mod)%mod;
ans=(ans+wi)%mod;
}
else{
wi=(sum3[p1][0]-sum3[p2][0])%mod*mi;
wi=(wi-(sum3[p1][1]-sum3[p2][1])%mod*(i-1)%mod*mi%mod+mod)%mod;
ans=(ans+wi)%mod;
}
}
solve(l,mid);
solve(mid+1,r);
ans=(ans%mod+mod)%mod;
}
int main(){
prepare();
solve(1,n);
cout<<ans<<"
";
return 0;
}