3745: [Coci2015]Norma
我们对于a序列分治,枚举左端点(从右往左)维护 M I N MIN MIN和 M A X MAX MAX,右端点同时更新两个指针j,k,表示 a [ m i d + 1 , j ] ≤ M A X a[mid+1,j] \le MAX a[mid+1,j]≤MAX和 M I N ≤ a [ m i d + 1 , k ] MIN\le a[mid+1,k] MIN≤a[mid+1,k]。
于是右半边被分成三份。
这里设 j < k j<k j<k
1. M I N ∗ M A X ∗ ∑ t = m i d + 1 j ( t − i + 1 ) MIN * MAX * \sum_{t=mid+1}^{j} (t-i+1) MIN∗MAX∗∑t=mid+1j(t−i+1)等差数列求一下就可以了。
2. M I N ∗ ∑ t = j + 1 k ( m i n [ j + 1 , t ] ∗ ( t − i + 1 ) ) MIN * \sum_{t=j+1}^{k}(min[j+1,t] * (t-i+1)) MIN∗∑t=j+1k(min[j+1,t]∗(t−i+1))预处理出 m i n [ j + 1 , t ] ∗ t min[j+1,t] * t min[j+1,t]∗t和 m i n [ j + 1 , t ] min[j+1,t] min[j+1,t]的前缀和。
3. ∑ t = k + 1 R ( m i n [ j + 1 , t ] ∗ m a x [ j + 1 , t ] ∗ ( t − i + 1 ) ) \sum_{t=k+1}^R(min[j+1,t]*max[j+1,t]*(t-i+1)) ∑t=k+1R(min[j+1,t]∗max[j+1,t]∗(t−i+1))同2
爆精度查了半天QAQ
#include<cstdio>
#include<algorithm>
using namespace std;
const int MOD=1e9,MAXN=500005;
int n;long long Ans,a[MAXN],sn[MAXN],snj[MAXN],sm[MAXN],smj[MAXN],snm[MAXN],snmj[MAXN];
#include<cctype>
int read(){
int ret=0;char ch=getchar();bool f=1;
for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
for(; isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;
return f?ret:-ret;
}
void Solve(int L,int R){
if(L==R){Ans=(Ans+a[L]*a[L]%MOD)%MOD;return;}int mid=(R+L)>>1;
Solve(L,mid),Solve(mid+1,R);
sn[mid]=snj[mid]=sm[mid]=smj[mid]=snm[mid]=snmj[mid]=0;
long long MAX=0,MIN=1<<30;
for(int i=mid+1;i<=R;i++){
MAX=max(MAX,a[i]),MIN=min(MIN,a[i]);
sn[i]=(sn[i-1]+MIN)%MOD;sm[i]=(sm[i-1]+MAX)%MOD;
snj[i]=(snj[i-1]+MIN*i%MOD)%MOD;smj[i]=(smj[i-1]+MAX*i%MOD)%MOD;
snm[i]=(snm[i-1]+MIN*MAX%MOD)%MOD;snmj[i]=(snmj[i-1]+MIN*MAX%MOD*i%MOD)%MOD;
}
MAX=0,MIN=1<<30;
for(int i=mid,j=mid,k=mid;i>=L;i--){
MAX=max(MAX,a[i]),MIN=min(MIN,a[i]);
while(j<R&&a[j+1]<=MAX) j++;
while(k<R&&a[k+1]>=MIN) k++;
int x=min(j,k),y=max(j,k);
Ans=(Ans+MAX*MIN%MOD*(1ll*(mid-i+x-i+3)*(x-mid)/2%MOD))%MOD;
Ans=(Ans+(snmj[R]-snmj[y]-(snm[R]-snm[y])*(i-1)%MOD)%MOD+MOD)%MOD;
if(k<j) Ans=(Ans+MAX*(snj[y]-snj[x]-(sn[y]-sn[x])*(i-1)%MOD)%MOD+MOD)%MOD;
else Ans=(Ans+MIN*(smj[y]-smj[x]-(sm[y]-sm[x])*(i-1)%MOD)%MOD+MOD)%MOD;
}
}
int main(){
n=read();for(int i=1;i<=n;i++) a[i]=read();
Solve(1,n);printf("%lld\n",Ans);
return 0;
}