• 「Newcoder练习赛40D」小A与最大子段和


    题目

    挺好的一道题

    我们考虑把(i)作为选取的最大子段的结束位置,我们如何往前计算贡献呢

    考虑一下这个乘上其在队列中的位置可以表示为这个数被算了多少次,而我们往前扩展一位当前已经被扩展的就会被计算一次

    (s_i)表示序列的前缀和

    扩展一次

    [s_i-s_{i-1} ]

    再扩展一次

    [s_i-s_{i-1}+s_i-s_{i-2} ]

    发现如果我们往前算到第(j)项的话贡献就是

    [(i-j+1) imes s_i-sum_{k=j-1}^{i-1}s_k ]

    如果对前缀和序列在求一个前缀和,得到一个(S)序列就变成了这个柿子

    [i imes s_i-s_ij+s_i-S_{i-1}+S_{j-2} ]

    发现只有

    [-s_ij+S_{j-2} ]

    会影响我们的决策,所以考虑让这一项最大就好了

    [b=-s_ij+S_{j-2} ]

    [s_ij+b=S_{j-2} ]

    这不是标准的斜率式吗,把((j,S_{j-2}))看成点,(s_i)看成斜率找到一个最优决策点就好了

    自然凸壳上二分斜率了

    第一次写这个东西,细节不少

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define maxn 200005
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    LL s[maxn],pre[maxn];
    LL ans=0;
    int q[maxn],h=1,t,n;
    inline LL X(int i) {return (LL)i;}
    inline LL Y(int i) {return pre[((i-2)>0)?(i-2):0];}
    inline double K(int a,int b) {
    	if(X(a)==X(b)) return 9999999999;
    	return (double)(Y(a)-Y(b))/(double)(X(a)-X(b));
    }
    inline void ins(int x) {
    	while(h<t&&K(q[t-1],q[t])<K(q[t-1],x)) t--;
    	q[++t]=x;
    }
    inline int find(LL x) {
    	if(h==t) return q[t];
    	if(h==t-1) {
    		if(K(q[h],q[t])<x) return q[h];
    		return q[t];
    	}
    	int l=h,r=t;
    	while(l<=r) {
    		if(l==r-1) {
    			if(K(q[l],q[r])<x) return q[l];
    			return q[r];
    		}
    		int mid=l+r>>1;
    		if(mid+1>r) break;//细节1
    		if(K(q[mid],q[mid+1])<x) r=mid;//细节2,不能将mid排除,这样在终止条件的时候就计算不到了
    			else l=mid+1;
    	}
    	return q[t];
    }
    int main()
    {
    	scanf("%d",&n);
    	for(re int i=1;i<=n;i++) scanf("%lld",&s[i]);
    	for(re int i=1;i<=n;i++) s[i]+=s[i-1];
    	for(re int i=1;i<=n;i++) pre[i]=pre[i-1]+s[i];
    	ins(1);ans=s[1];
    	for(re int i=2;i<=n;i++) {
    		ins(i);int x=find(s[i]);
    		ans=max(ans,(LL)(i+1)*s[i]-s[i]*x-pre[i-1]+pre[((x-2)>0)?(x-2):0]);
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    nginx添加location跳转后不生效
    UniApp微信小程序授权获取用户当前位置信息
    VS创建Core项目体验跨平台,部署在docker上运行(启用docker支持)
    在Unity中渲染一个黑洞
    一个简简单单的红点系统框架
    十一、Abp vNext 基础篇丨测试
    Abp vNext 番外篇-疑难杂症丨浅谈扩展属性与多用户设计
    十、Abp vNext 基础篇丨权限
    九、Abp vNext 基础篇丨评论聚合功能
    Abp vNext 番外篇-疑难杂症丨nginx反向代理-部署
  • 原文地址:https://www.cnblogs.com/asuldb/p/10392407.html
Copyright © 2020-2023  润新知