• 义乌集训7.8 contest 1题解


    2021.7.8D

    ​ 鉴于前3道题比较简单,就不写题解了,主要写一写T4的题解。

    Description:

    ​ 给定一个序列 (a),定义一个区间 ([l,r]) 的最大子段和为 ([l,r]) 的一段连续子区间的和,满足其为 ([l,r]) 所有连续子区间和中最大的一个。

    ​ 求出所有 (1le lle rle n) 的区间 ([l,r]) 的最大子段和的和,答案对 (2^{64}) 取模。

    ​ 具体来说,假设答案为 (x),你需要输出最小的非负整数 (y),满足 (x)(y)(2^{64}) 同余。

    Input:

    ​ 第一行一个数 (n)

    ​ 第二行 (n) 个数,第 (i) 个表示 (a_i)

    Output:

    ​ 一行一个数表示答案。

    Sample1 Input:

    5
    1 -1 1 -1 1
    

    Sample1 Output:

    11
    

    Sample2 Input:

    5
    1 -2 3 -4 5
    

    Sample2 Output:

    39
    

    Hint:

    本题采用子任务评测。

    对于 (30\%) 的数据,(1 leq n leq 10^{3})

    对于另外 (20\%) 的数据,(a_i geq 0)

    对于 (100\%) 的数据,(1 leq n leq 10^{5},-10^{9} leq a_i leq 10^{9})

    题目分析:

    ​ 前两个数据点的分数比较好拿。(只要别脑抽写个高精一般就不会死,自然溢出是个好东西

    ​ 正解:考虑分治。对于一段区间([l,r])内的所有答案,即 (l leq i leq j leq r) 的所有([i,j])内的最大子段和。我们找到中点(mid),答案便可以拆成([l,mid])([mid+1,r])以及 (l leq i leq mid < j leq r) 的贡献之和。前两个贡献递归处理,我们只需考虑第三种贡献的求法。

    ​ 对于一对([i,j]),它可能的最大子段和分三种情况:([i,mid])的最大子段和,([mid+1,j])的最大子段和,跨过(mid)的最大子段和(即一段以(mid)为右端点的最大后缀加上以(mid)为左端点的最大前缀)

    ​ 那么如果我们固定了 (i),那么对于({forall } mid+1 leq j leq r),我们需要比较这三种情况的大小取最大值。

    ​ 考虑分类讨论——

    ​ 我们设以(mid)为右端点且左端点大于 (i) 的最大后缀为(A_i),以(mid)为左端点且右端点小于 (i) 的最大前缀为(B_i)([i,mid])的最大子段和为(C_i)([mid+1,i])的最大子段和为(D_i)。我们可以简单地发现(A,B,C,D)都有显然的单调性。

    ​ 1‘ (C_i geq D_j)时,对于固定的 (i) 我们可以通过(two-points)或二分迅速的找到对应的 (j) 的上界,设其为 (k) ,那么我们只需比较 (mid+1 leq j leq k)(j)({A_i}+{B_j})(C_i) 的大小。

    ​ 1‘’ (A_i+B_j leq C_i),即 (C_i-A_I geq B_j) ,那么我们可以在 ([mid+1,k]) 中二分出一个分界线 (p),满足 (mid+1 leq j leq p)(C_i-A_I geq B_j),用前缀和之类的东西计算其贡献。

    ​ 2'' (A_i+B_j >C_i),也就是 (p+1 leq j leq k) ,计算其贡献。

    ​ 2’ (C_i < D_j)时,我们按照同样的方法计算。

    ​ 于是这道题就愉快地结束了。

    代码如下(马蜂很丑,不喜勿喷)——

    #include<bits/stdc++.h>
    #define N 100005
    #define LL long long
    #define ULL unsigned long long
    #define inf 2147483647
    using namespace std;
    int n;LL a[N],A[N],B[N],C[N],D[N],S[N];ULL ans;
    inline void solve(int l,int r){
    	if(l>r) return;if(l==r){ans+=a[r]-a[l-1];/*cout<<l<<' '<<r<<' '<<ans<<'
    ';*/return;}int mid=l+r>>1;solve(l,mid),solve(mid+1,r);B[mid]=A[mid+1]=-inf;LL res=0,Max=-inf;
    	for(register int i=mid;i>=l;i--){A[i]=max(A[i+1],a[mid]-a[i-1]);if(res<0) res=0;res+=a[i]-a[i-1],Max=max(Max,res),C[i]=Max;/*cout<<i<<' '<<mid<<' '<<C[i]<<'
    ';*/}
    	Max=-inf,res=0;for(register int i=mid+1;i<=r;i++){B[i]=max(B[i-1],a[i]-a[mid]);if(res<0) res=0;res+=a[i]-a[i-1],Max=max(Max,res),D[i]=Max;/*cout<<mid+1<<' '<<i<<' '<<D[i]<<'
    ';*/}
    	int i=mid,j=mid+1;S[j-1]=0;while(i>=l){
    		while(j<=r&&D[j]<=C[i]) S[j]=S[j-1]+B[j],j++;int L=mid+1,R=j-1,num=j;
    		while(L<=R){int M=L+R>>1;if(C[i]-A[i]<=B[M]) R=M-1,num=M;else L=M+1;}
    		ans+=1ull*C[i]*(num-mid-1)+(ULL)S[j-1]-(ULL)S[num-1]+1ull*(j-num)*A[i],i--;
    	}
    	i=mid,j=mid+1,S[i+1]=0;while(j<=r){
    		while(i>=l&&D[j]>C[i]) S[i]=S[i+1]+A[i],i--;int L=i+1,R=mid,num=i;
    		while(L<=R){int M=L+R>>1;if(D[j]-B[j]<=A[M]) L=M+1,num=M;else R=M-1;}
    		ans+=1ull*D[j]*(mid-num)+(ULL)S[i+1]-(ULL)S[num+1]+1ull*(num-i)*B[j],j++;
    	}
    //	cout<<l<<' '<<r<<' '<<mid<<' '<<ans<<'
    ';
    }
    inline int read(){
    	int ret=0,f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-') f=-f;ch=getchar();}
    	while(isdigit(ch)) ret=(ret<<1)+(ret<<3)+ch-'0',ch=getchar();return ret*f;
    }
    int main(){
    	n=read();for(register int i=1;i<=n;i++) a[i]=read()+a[i-1];solve(1,n),cout<<ans;return 0;
    }
    
  • 相关阅读:
    chromedriver与chrome各版本及下载地址
    chromedriver和firefox driver的安装过程
    ubuntu python及python IDLE 的安装
    Ubuntu14.04安装及配置mysql5.7.19
    容器集群管理平台的比较
    Android调试神器stetho使用详解和改造
    Vue CLI 3搭建vue+vuex 最全分析
    不会PPT配色没关系,有这些配色网站,也能让你的PPT配色美到极致
    15个超赞的配色网站,建议收藏
    10个超好用的配色网站
  • 原文地址:https://www.cnblogs.com/jiangxuancheng/p/14987843.html
Copyright © 2020-2023  润新知