「COCI2014-2015#2」Norma 题解

本文网址:https://www.cnblogs.com/zsc985246/p/16621286.html ,转载请注明出处。

题目大意

给定一个 n 个数的序列 a,求

ni=1nj=i(ji+1)min(ai,ai+1,,aj)max(ai,ai+1,,aj)

即:求序列 a 的所有子序列的 最小值×最大值×序列长度 的和。

思路

考虑分治

那么问题转化为:计算区间左端点在 [l,mid],右端点在 (mid,r] 时对答案的贡献。

令区间左端点为 i,区间 [i,mid] 中最大值为 maxx,最小值为 minn

p 为满足 minn<min(amid+1,amid+2,,aq) 的最大 p

q 为满足 maxx>max(amid+1,amid+2,,ap) 的最大 q

w1=min(p,q)w2=max(p,q)

则对于 (mid,r] 这段区间,可以分为三个小区间:

  1. (mid,w1]:所有子序列的最大最小值均为定值;

  2. (w1,w2]:所有子序列的最大最小值有一个为定值;

  3. (w2,r]:所有子序列的最大最小值均不为定值。

第一个区间对答案的贡献为:

w1j=mid+1(ji+1)min(ai,ai+1,,aj)max(ai,ai+1,,aj)=w1j=mid+1(ji+1)×minn×maxx                                              =minn×maxx×w1j=mid+1(ji+1)                                                                       =minn×maxx×((mid+1i+1)+(w1i+1))×(w1(mid+1)+1)2=minn×maxx×(w1+mid2×i+3)×(w1mid)2           

第二个区间对答案的贡献分两种情况:

  1. p>q

那么 minn 是定值,贡献为:

qj=mid+1(ji+1)min(ai,ai+1,,aj)max(ai,ai+1,,aj)=qj=mid+1(ji+1)×minn×max(ai,ai+1,,aj)                     =minn×qj=mid+1(ji+1)×max(ai,ai+1,,aj)                      

对于后面的求和,实际上是可以前缀和优化的。只需要将求和中的 i 拆分出来。

=minn×qj=mid+1(ji+1)×max(amid+1,amid+2,,aj)                       =minn×qj=mid+1(jmid+midi+1)×max(amid+1,amid+2,,aj)=minn×(qj=mid+1(midi+1)×max(amid+1,amid+2,,aj)+qj=mid+1(jmid)×max(amid+1,amid+2,,aj))

化简到这里,我们发现已经可以前缀和优化了。

s1mid=0

s1x(x(mid,r])=s1x1+((xmid)×max(amid+1,amid+2,,ax)

s1mid=0

s1x(x(mid,r])=s1x1+max(amid+1,amid+2,,ax)

所以原式化为:

minn×((midi+1)×(s1ps1q)+(s1ps1q))

  1. p<q

同 1 可得:

s2mid=0

s2x(x(mid,r])=s2x1+((xmid)×min(amid+1,amid+2,,ax)

s2mid=0

s2x(x(mid,r])=s2x1+min(amid+1,amid+2,,ax)

对答案的贡献为:

maxx×((midi+1)×(s2qs2p)+(s2qs2p))

第三个区间对答案的贡献计算与第二个区间的思路大体相同:

s3mid=0

s3x(x(mid,r])=s3x1+((xmid)×min(amid+1,amid+2,,ax)×max(amid+1,amid+2,,ax)

s3mid=0s3x(x(mid,r])=s3x1+min(amid+1,amid+2,,ax×max(amid+1,amid+2,,ax))

对答案的贡献为:

(midi+1)×(s3rs3w2)+(s3rs3w2)

最后综合一下即是答案。

代码实现

#include<bits/stdc++.h>
#define ll long long
const ll N=500010;
const ll mod=1e9;
using namespace std;

ll n,a[N],s1[N],s1_[N],s2[N],s2_[N],s3[N],s3_[N];
ll ans;

void f(ll l,ll r){
    if(l==r){
		ans=(ans+a[l]*a[l]%mod+mod)%mod;
		return;
	}
    ll mid=l+r>>1;
    ll minn=a[mid+1],maxx=a[mid+1];
    s2[mid]=s1[mid]=s3[mid]=s2_[mid]=s1_[mid]=s3_[mid]=0;
    for(ll i=mid+1;i<=r;++i){
        minn=min(minn,a[i]),maxx=max(maxx,a[i]);
		s1[i]=(s1[i-1]+maxx*(i-mid)%mod+mod)%mod;
		s1_[i]=(s1_[i-1]+maxx+mod)%mod;
        s2[i]=(s2[i-1]+minn*(i-mid)%mod+mod)%mod;
		s2_[i]=(s2_[i-1]+minn+mod)%mod;
        s3[i]=(s3[i-1]+minn*maxx%mod*(i-mid)%mod+mod)%mod;
		s3_[i]=(s3_[i-1]+minn*maxx%mod+mod)%mod;
    }
    ll i,p,q;
    i=p=q=mid;
    minn=maxx=a[mid];
    while(i>=l){
        minn=min(minn,a[i]),maxx=max(maxx,a[i]);
        while(p<r&&a[p+1]>minn)++p;
        while(q<r&&a[q+1]<maxx)++q;
        ll w1=min(p,q),w2=max(p,q);
        //1 
        if(w1>mid)ans=(ans+minn*maxx%mod*((mid-2*i+w1+3)*(w1-mid)/2%mod)%mod+mod)%mod;
        //2 
        if(p>q){
        	ans+=(minn*((mid-i+1)*(s1_[p]-s1_[q]+mod)%mod+(s1[p]-s1[q]+mod)%mod)%mod+mod)%mod;
        }
        if(p<q){
        	ans+=(maxx*((mid-i+1)*(s2_[q]-s2_[p]+mod)%mod+(s2[q]-s2[p]+mod)%mod)%mod+mod)%mod;
        }
        //3 
        ans+=(((mid-i+1)*(s3_[r]-s3_[w2]+mod)%mod+(s3[r]-s3[w2]+mod)%mod)%mod+mod)%mod;
        i--;
    }
    f(l,mid);
	f(mid+1,r);
}

int main(){
	
	scanf("%lld",&n);
	for(ll i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	f(1,n);
	printf("%lld\n",ans%mod);
	
	return 0;
}
posted @   zsc985246  阅读(254)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示