分治到一个区间时枚举左端点,然后分类讨论一下就好了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
const int N=500010;
const int M=1000000000;
int k,n,m,p;
int a[N];
int mn[N],mx[N],smn[N],smx[N],imn[N],imx[N],smnmx[N],imnmx[N];
int Ans;
inline void Add(int& x,int y){
x=(x+y)%M;
}
inline int Sum(int l,int r){
return 1ll*(r+l)*(r-l+1)/2%M;
}
void Solve(int l,int r){
if(l==r){
Add(Ans,1ll*a[l]*a[l]%M);
// printf("%d %d %d\n",l,r,a[l]*a[l]);
return;
}
int Mid=l+r>>1;
Solve(l,Mid);Solve(Mid+1,r);
mn[Mid+1]=mx[Mid+1]=smn[Mid+1]=smx[Mid+1]=a[Mid+1];
smnmx[Mid+1]=1ll*mn[Mid+1]*mx[Mid+1]%M;
imnmx[Mid+1]=1ll*smnmx[Mid+1]*(Mid+2)%M;
imn[Mid+1]=imx[Mid+1]=1ll*(Mid+2)*a[Mid+1]%M;
for(int i=Mid+2;i<=r;i++){
mn[i]=min(mn[i-1],a[i]);mx[i]=max(mx[i-1],a[i]);
smn[i]=(smn[i-1]+mn[i])%M;smx[i]=(smx[i-1]+mx[i])%M;
imn[i]=(imn[i-1]+1ll*mn[i]*(i+1))%M;imx[i]=(imx[i-1]+1ll*mx[i]*(i+1))%M;
smnmx[i]=(smnmx[i-1]+1ll*mn[i]*mx[i])%M;
imnmx[i]=(imnmx[i-1]+1ll*mn[i]*mx[i]%M*(i+1))%M;
}
int j=Mid,k=Mid;
int Mn=a[Mid],Mx=a[Mid];
imn[Mid]=smn[Mid]=imx[Mid]=smx[Mid]=0;
imnmx[Mid]=smnmx[Mid]=0;
for(int i=Mid;i>=l;i--){
int Res=Ans;
Mn=min(Mn,a[i]);Mx=max(Mx,a[i]);
while(j<r&&mn[j+1]>=Mn)j++;
while(k<r&&mx[k+1]<=Mx)k++;
Add(Ans,1ll*Mn*Mx%M*Sum(Mid+2-i,min(j,k)-i+1)%M);
if(j<k){
Add(Ans,1ll*Mx*(imn[k]-imn[j])%M);
Add(Ans,-1ll*Mx*i%M*(smn[k]-smn[j])%M);
Add(Ans,(imnmx[r]-imnmx[k])%M);
Add(Ans,-1ll*i*(smnmx[r]-smnmx[k])%M);
}else{
Add(Ans,1ll*Mn*(imx[j]-imx[k])%M);
Add(Ans,-1ll*Mn*i%M*(smx[j]-smx[k])%M);
Add(Ans,(imnmx[r]-imnmx[j])%M);
Add(Ans,-1ll*i*(smnmx[r]-smnmx[j])%M);
}
}
}
int main(){
Read(n);
for(int i=1;i<=n;i++)Read(a[i]);
Solve(1,n);
cout<<(Ans+M)%M<<endl;
return 0;
}