这题推式子恶心。。。。。
考虑分治,每次统计跨过(mid)的所有区间的答案和。(i)从(mid-1)到(l)枚举,统计以(i)为左端点的所有区间。
我们先维护好([i,mid])区间内最小值(mn)和最大值(mx)。我们可以想到,对于某一个左端点,它的右端点(j)在一定的范围内,最小值和最大值都不会变。这里就看到一些可以重复利用并快速计算的信息了。
维护两个指针(p,q),分别表示([mid+1,r])内元素值第一个小于(mn/)大于(mx)的位置,那么(sumlimits_{j=mid+1}^rans[i,j])就可以分成三类讨论。暂时假设(p<q)。
(jin[mid+1,p-1])时,区间的最值不变,都是(mn,mx),直接高斯求和
[ansleftarrow mncdot mxsumlimits_{j=mid+1}^{p-1}j-i+1
]
(jin[p,q-1])时,区间最大值不变,但最小值取的是([mid+1,j])里的了。预处理(mid+1)到(r)的前缀最小值(min_j),同时记录(min_j)和(min_jcdot j)的前缀和((pge q)同理)
[ansleftarrow mxsumlimits_{j=p}^{q-1}min_j(j-i+1)
]
[ansleftarrow mxsumlimits_{j=p}^{q-1}min_jcdot j+mx(1-i)sumlimits_{j=p}^{q-1}min_j
]
(jin[q,r])时,最值和(mn,mx)无关了,记录(min_jmax_j)和(min_jmax_jcdot j)的前缀和
[ansleftarrow sumlimits_{j=q}^rmin_jmax_j(j-i+1)
]
[ansleftarrow sumlimits_{j=q}^rmin_jmax_jcdot j+(1-i)sumlimits_{j=q}^rmin_jmax_j
]
容易发现(mn,mx,p,q)都是单调移动的,那么就大功告成啦!
#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG LL//常数大也无所谓了
#define G if(++ip==ie)fread(ip=buf,1,N,stdin)
#define A(V) (ans+=V)%=YL
using namespace std;
const LL N=1<<19,YL=1e9;
char buf[N],*ie=buf+N,*ip=ie-1;
LL ans,a[N],mns[N],mxs[N],mnj[N],mxj[N],mms[N],mmj[N];
inline LL in(){
G;while(*ip<'-')G;
R x=*ip&15;G;
while(*ip>'-'){x*=10;x+=*ip&15;G;}
return x;
}
inline LL S(R l,R r){//高斯求和
return (l+r)*(r-l+1)/2%YL;
}
void solve(R l,R r){
if(l==r){A(a[l]*a[l]);return;}
R m=(l+r)>>1,i,j,p,q,mn=YL,mx=0;
solve(l,m);solve(m+1,r);
mns[m]=mxs[m]=mnj[m]=mxj[m]=mms[m]=mmj[m]=0;
for(j=m+1;j<=r;++j){//预处理,变量名不解释
mn=min(mn,a[j]);mx=max(mx,a[j]);
mns[j]=(mns[j-1]+mn)%YL;
mxs[j]=(mxs[j-1]+mx)%YL;
mnj[j]=(mnj[j-1]+mn*j)%YL;
mxj[j]=(mxj[j-1]+mx*j)%YL;
mms[j]=(mms[j-1]+mn*mx)%YL;
mmj[j]=(mmj[j-1]+mn*mx%YL*j)%YL;
}
mn=YL;mx=0;
for(p=q=m+1,i=m;i>=l;--i){//计算答案
mn=min(mn,a[i]);mx=max(mx,a[i]);
while(p<=r&&mn<a[p])++p;//单调移动
while(q<=r&&mx>a[q])++q;
if(p<q){
A(mn*mx%YL*S(m-i+2,p-i));//注意做减法的都要加一下模数
A(mx*(mnj[q-1]-mnj[p-1]+YL)+mx*(mns[q-1]-mns[p-1]+YL)%YL*(1-i+YL));
A(mmj[r]-mmj[q-1]+(mms[r]-mms[q-1]+YL)*(1-i+YL));
}
else{
A(mn*mx%YL*S(m-i+2,q-i));
A(mn*(mxj[p-1]-mxj[q-1]+YL)+mn*(mxs[p-1]-mxs[q-1]+YL)%YL*(1-i+YL));
A(mmj[r]-mmj[p-1]+(mms[r]-mms[p-1]+YL)*(1-i+YL));
}
}
}
int main(){
R n=in();
for(R i=1;i<=n;++i)a[i]=in();
solve(1,n);
printf("%lld
",ans);
return 0;
}