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,r l , r ,找到他的中间点 mid m i d
枚举 l mid l m i d ,我们的目标是对于所有 [l,mid] [ l , m i d ] 找出他在所有 [mid+1,r] [ m i d + 1 , r ] 区间内的答案
对于每个 i i ,维护两个指针
满足 [mid+1,u] [ m i d + 1 , u ] 中的数全部大于 [i,mid] [ i , m i d ] 的最小值且u最大
满足 [mid+1,v] [ m i d + 1 , v ] 中的数全部小于 [i,mid] [ i , m i d ] 的最大值且v最大
于是我们有三种讨论,不妨假设u < v,设 mn m n 表示 [i,mid] [ i , m i d ] 中的最小值, mx m x 表示 [i,mid] [ i , m i d ] 中的最大值
对于 [mid+1,u] [ m i d + 1 , u ] ,他的贡献为
∑j=mid+1umx∗mn+(j−i+1) ∑ j = m i d + 1 u m x ∗ m n + ( 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 + 1 v m x ∗ m i n [ m i d + 1 , j ] ∗ ( j − i + 1 )
拆一下就变成了这样
mx∗∑j=u+1vmin[mid+1,j]∗j−min(mid+1,j)∗(i−1) m x ∗ ∑ j = u + 1 v m i n [ m i d + 1 , j ] ∗ j − m i n ( m i d + 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 + 1 r m a x [ m i d + 1 , j ] ∗ m i n ( m i d + 1 , j ) ∗ j − m a x ( m i d + 1 , j ) ∗ m i n ( m i d + 1 , j ) ∗ ( i − 1 )
预处理前缀和仍然可以 O(1) O ( 1 )
然后又是愉快的 nlogn n l o g n 了
#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;
}