题意:
分析:
- 暴力
(O(n log n)) 预处理 ST表 然后 (O(n^2)) 枚举左右端点
- 正解
我们要优化统计答案的复杂度,也就是说我们需要大概 (O(n log n)) 的复杂度 来统计答案
很容易想到每一个点作为最大值和最小值的影响是一段区间,那么我们就递归通过分治来统计区间的贡献,和 CDQ 分治的思想差不多,我们只需要统计跨过区间中点的影响,剩下的递归下去
具体来说,每一次分治中,我们枚举左端点 (i) ,统计以 (i) 为左端点的序列的答案,分三种情况讨论 , 默认 (ple q)
变量声明:
mx = $ max(a_idots a_{mid})$ ; mn = $ min(a_idots a_{mid})$
mna = (sum mn) ; mnb = (sum mn imes i)
mxa = (sum mx) ; mxb = $sum mx imes i $
mma = (sum mx imes mn) ; mmb = (sum mx imes mn imes i)
p 表示满足 (mn leqslant min { a[mid!+!1] cdots a[j] }) 的最大的 p 的位置
q 表示满足 (mx geqslant max { a[mid!+!1] cdots a[k] }) 的最大的 q 的位置。
- (mx,mn) 都取 ([mid+1,p])
(ans Leftrightarrow sum mn imes mx imes (j-i+1))
- (mx) 取 (mn) 不取 ([p,q])
(ans Leftrightarrow mx imes sum min_j imes (j-i+1))
- (mx,mn) 都不取 ([q,r])
(ansLeftrightarrow sum max_j imes min_j imes (j-i+1))
代码:
#include<bits/stdc++.h>
using namespace std;
namespace zzc
{
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 5e5+5;
const long long mod = 1e9;
long long a[maxn],mxa[maxn],mxb[maxn],mna[maxn],mnb[maxn],mma[maxn],mmb[maxn];
long long ans,n,mn,mx;
void qm(long long x){return (void)(ans=(ans+x>=mod?ans+x-mod:ans+x));}
long long S(long long l,long long r){return (long long)(l+r)*(r-l+1)/2%mod;}
void solve(int l,int r)
{
if(l==r){return (void)(qm(a[l]*a[l]%mod));}
long long mid=(l+r)>>1;
solve(l,mid);solve(mid+1,r);
mn=mod;mx=0;
mxa[mid]=mxb[mid]=mna[mid]=mnb[mid]=mma[mid]=mmb[mid]=0;
for(int j=mid+1;j<=r;j++)
{
mn=min(mn,a[j]);mx=max(mx,a[j]);
mxa[j]=(mxa[j-1]+mx)%mod;
mxb[j]=(mxb[j-1]+mx*j%mod)%mod;
mna[j]=(mna[j-1]+mn)%mod;
mnb[j]=(mnb[j-1]+mn*j%mod)%mod;
mma[j]=(mma[j-1]+mn*mx%mod)%mod;
mmb[j]=(mmb[j-1]+mn*mx%mod*j%mod)%mod;
}
mn=mod;mx=0;
for(int q=mid+1,p=mid+1,i=mid;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)
{
qm(mn*mx%mod*S(mid-i+2,p-i)%mod);
qm((mnb[q-1]-mnb[p-1]+mod)*mx%mod+(1-i+mod)*mx%mod*(mna[q-1]-mna[p-1]+mod)%mod);
qm((mmb[r]-mmb[q-1]+mod)%mod+(1-i+mod)%mod*(mma[r]-mma[q-1])%mod);
}
else
{
qm(mn*mx%mod*S(mid-i+2,q-i)%mod);
qm((mxb[p-1]-mxb[q-1]+mod)*mn%mod+(1-i+mod)*mn%mod*(mxa[p-1]-mxa[q-1]+mod)%mod);
qm((mmb[r]-mmb[p-1]+mod)%mod+(1-i+mod)%mod*(mma[r]-mma[p-1]+mod)%mod);
}
}
}
void work()
{
n=read();
for(int i=1;i<=n;i++) a[i]=read();
solve(1,n);
printf("%lld
",ans%mod);
}
}
int main()
{
zzc::work();
return 0;
}