考虑分治
左端点在左边 右端点在右边
枚举左端点 分情况讨论最大最小分别在哪边 然后前缀和处理
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(ll &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const ll P=(ll)1e9;
const int N=500005;
ll n,a[N];
ll sum1[N],sum2[N],sum3[N],sum4[N],sum5[N],sum6[N];
inline ll Sum(ll s,ll t){
return ((s+t)*(t-s+1)/2)%P;
}
ll ans;
inline void Solve(int l,int r){
if (l==r){
ans+=a[l]*a[l]%P; ans=(ans%P+P)%P; return;
}
int mid=(l+r)>>1;
ll mx=-1LL<<30,mn=1LL<<30; sum1[mid]=sum2[mid]=sum3[mid]=sum4[mid]=sum5[mid]=sum6[mid]=0;
for (int i=mid+1;i<=r;i++)
{
mx=max(mx,a[i]); mn=min(mn,a[i]);
sum1[i]=mx*mn%P; (sum1[i]+=sum1[i-1])%=P;
sum2[i]=mx*mn%P*i%P; (sum2[i]+=sum2[i-1])%=P;
sum3[i]=mn; (sum3[i]+=sum3[i-1])%=P;
sum4[i]=mn*i%P; (sum4[i]+=sum4[i-1])%=P;
sum5[i]=mx; (sum5[i]+=sum5[i-1])%=P;
sum6[i]=mx*i%P; (sum6[i]+=sum6[i-1])%=P;
}
int j=mid,k=mid; ll u=a[mid],v=a[mid],s,t;
for (int i=mid;i>=l;i--,u=min(u,a[i]),v=max(v,a[i])){
while (j+1<=r && a[j+1]>=u) j++;
while (k+1<=r && a[k+1]<=v) k++;
s=mid+1,t=min(j,k);
if (s<=t)
{
ans+=u*v%P*Sum(s-i+1,t-i+1)%P; ans=(ans%P+P)%P;
}
s=max(j,k)+1,t=r;
if (s<=t)
{
ans+=sum2[t]-sum2[s-1]; ans=(ans%P+P)%P;
ans+=(ll)(1-i)*(sum1[t]-sum1[s-1])%P; ans=(ans%P+P)%P;
}
s=min(j,k)+1,t=max(j,k);
if (s<=t)
{
if (j<=k){
ans+=v*(sum4[t]-sum4[s-1])%P; ans=(ans%P+P)%P;
ans+=v*(1-i)%P*(sum3[t]-sum3[s-1])%P; ans=(ans%P+P)%P;
}else{
ans+=u*(sum6[t]-sum6[s-1])%P; ans=(ans%P+P)%P;
ans+=u*(1-i)%P*(sum5[t]-sum5[s-1])%P; ans=(ans%P+P)%P;
}
}
}
Solve(l,mid); Solve(mid+1,r);
}
int main()
{
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n);
for (int i=1;i<=n;i++) read(a[i]);
Solve(1,n);
printf("%lld\n",ans);
return 0;
}