Description
Input
第1行,一个整数N; 第2~n+1行,每行一个整数表示序列a。
Output
输出答案对10^9取模后的结果。
Sample Input
4
2
4
1
4
Sample Output
109
HINT
【数据范围】
N <= 500000
1 <= a_i <= 10^8
题解
还是分治
自己yy的东西t的一逼啊233333
对于一段区间l,rl,r,找到他的中间点midmid
枚举l midl mid,我们的目标是对于所有[l,mid][l,mid]找出他在所有[mid+1,r][mid+1,r]区间内的答案
对于每个ii,维护两个指针
满足[mid+1,u][mid+1,u]中的数全部大于[i,mid][i,mid]的最小值且u最大
满足[mid+1,v][mid+1,v]中的数全部小于[i,mid][i,mid]的最大值且v最大
于是我们有三种讨论,不妨假设u < v,设mnmn表示[i,mid][i,mid]中的最小值,mxmx表示[i,mid][i,mid]中的最大值
对于[mid+1,u][mid+1,u],他的贡献为
∑j=mid+1umx∗mn+(j−i+1)∑j=mid+1umx∗mn+(j−i+1)
显然可以直接O(1)O(1)
对于[u+1,v][u+1,v],他的贡献为
∑j=u+1vmx∗min[mid+1,j]∗(j−i+1)∑j=u+1vmx∗min[mid+1,j]∗(j−i+1)
拆一下就变成了这样
mx∗∑j=u+1vmin[mid+1,j]∗j−min(mid+1,j)∗(i−1)mx∗∑j=u+1vmin[mid+1,j]∗j−min(mid+1,j)∗(i−1)
预处理前缀和即O(1)O(1)
对于[v+1,r][v+1,r],他的贡献为
∑j=v+1rmax[mid+1,j]∗min(mid+1,j)∗j−max(mid+1,j)∗min(mid+1,j)∗(i−1)∑j=v+1rmax[mid+1,j]∗min(mid+1,j)∗j−max(mid+1,j)∗min(mid+1,j)∗(i−1)
预处理前缀和仍然可以O(1)O(1)
然后又是愉快的nlognnlogn了
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define LL long long
#define lc now<<1
#define rc now<<1|1
using namespace std;
const LL mod=1e9;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n;
LL a[510000];
LL s1[510000],s2[510000],s3[510000],s4[510000],s5[510000],s6[510000],ans;
/*
mn[mid+1,j]*j
mn[mid+1,j]
mx[mid+1,j]*j
mn[mid+1,j]
mx[mid+1,j]*mn[mid+1,j]*j
mx[mid+1,j]*mn[mid+1,j]
*/
LL C(int s,int t){return ((LL)s+t)*((LL)t-s+1)/2%mod;}
void sol(int l,int r)
{
if(l==r){ans=(ans+a[l]*a[l])%mod;return ;}
int mid=(l+r)>>1;
s1[mid]=s2[mid]=s3[mid]=s4[mid]=s5[mid]=s6[mid]=0;
LL u1=a[mid+1],u2=a[mid+1];
sol(l,mid);
sol(mid+1,r);
for(LL j=mid+1;j<=r;j++)
{
u1=min(u1,a[j]);u2=max(u2,a[j]);
//int u1=findhh(1,1,n,mid+1,j,0),u2=findhh(1,1,n,mid+1,j,1);
s1[j]=(s1[j-1]+(u1*j%mod))%mod;
s2[j]=(s2[j-1]+u1)%mod;
s3[j]=(s3[j-1]+(u2*j%mod))%mod;
s4[j]=(s4[j-1]+u2)%mod;
s5[j]=(s5[j-1]+u1*u2%mod*j%mod)%mod;
s6[j]=(s6[j-1]+u1*u2%mod)%mod;
}
// for(int j=mid+1;j<=r;j++)printf("%lld %lld\n",s1[j],s2[j]);
int u=mid,v=mid;
LL mn=a[mid],mx=a[mid];
for(LL i=mid;i>=l;i--)
{
mn=min(mn,a[i]);mx=max(mx,a[i]);
//int mn=findhh(1,1,n,i,mid,0),mx=findhh(1,1,n,i,mid,1);
while(u<r&&mn<a[u+1])u++;
while(v<r&&mx>a[v+1])v++;
ans=(ans+mx*mn%mod*C(mid-i+2,min(u-i+1,v-i+1))%mod)%mod;
if(u<=v)
{
ans=(ans+mx*((s1[v]-s1[u]+mod)%mod-((i-1)*(s2[v]-s2[u]+mod)%mod)%mod)%mod+mod)%mod;
ans=(ans+((s5[r]-s5[v]+mod)%mod)-((i-1)*(s6[r]-s6[v]+mod)%mod)+mod)%mod;
}
else
{
ans=(ans+mn*((s3[u]-s3[v]+mod)%mod-((i-1)*(s4[u]-s4[v]+mod)%mod)%mod)%mod+mod)%mod;
ans=(ans+((s5[r]-s5[u]+mod)%mod)-((i-1)*(s6[r]-s6[u]+mod)%mod)+mod)%mod;
}
}
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)a[i]=read();
sol(1,n);
printf("%lld\n",ans);
return 0;
}