序列问题
Description
Data Constraint
n
≤
Solution
考虑分治。
计算(
l
,
枚举左端点
p
,设
再找出第一个满足
max
(
amid+1
~
aq′
)≥
mx
的右端点
q′
,以及找出第一个满足
min
(
amid+1
~
aq′′
)≤
mi
的右端点
q′′
。
q′
和
q′′
将
mid
右边分成三段,对于每一段进行分类讨论维护答案即可。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define fo(i,j,l) for(i=j;i<=l;i++)
#define fd(i,j,l) for(i=j;i>=l;i--)
using namespace std;
typedef long long ll;
const ll N=520000,mo=1000000007;
ll s[N];
ll ans=0;
ll mx[N],mi[N],qx[N],qi[N],qa[N];
int n,m,j,k,l,i;
ll min(ll a,ll b)
{if(a<b)return a;else return b;}
ll max(ll a,ll b)
{if(a>b)return a;else return b;}
void ef(int l,int r)
{
if(l==r)return;
int mid=(l+r)/2;
int i,j;ll k1=s[mid+1],k2=s[mid+1];
fo(i,mid+1,r)
{
qx[i]=k1=max(k1,s[i]); qi[i]=k2=min(k2,s[i]);
qa[i]=k1*k2%mo;
}
if(l==5)
ans=ans;
qa[mid]=qa[r+1]=qx[r+1]=qi[r+1]=qx[mid]=qi[mid]=0;
fd(i,r-1,mid+1)qa[i]=(qa[i]+qa[i+1])%mo;
fo(i,mid+2,r+1)qx[i]=(qx[i]+qx[i-1])%mo,qi[i]=(qi[i]+qi[i-1])%mo;
k1=k2=s[mid]; ll k3,k4=mid+1,k5,k6=s[mid+1];
k3=k4; k5=k6;
fd(i,mid,l){
k1=max(k1,s[i]); k2=min(k2,s[i]);
while((k3<=r)&&(k5<k1)) k3++,k5=max(k5,s[k3]);
while((k4<=r)&&(k6>k2)) k4++,k6=min(k6,s[k4]);
ans=(ans+(k1*k2%mo)*(min(k3,k4)-mid-1))%mo;
ans=(ans+qa[max(k3,k4)])%mo;
ll an=ans;
if(k3<k4)ans=(ans+k2*(qx[k4-1] - qx[k3-1]))%mo;
else ans=(ans+k1*(qi[k3-1]-qi[k4-1]))%mo;
if(ans<an)
ans=ans;
}
ef(l,mid); ef(mid+1,r);
}
int main()
{
cin>>n;
fo(i,1,n)
scanf("%lld",&s[i]),ans=(ans+s[i]*s[i])%mo;
ef(1,n);
printf("%lld",ans);
}