zoukankan      html  css  js  c++  java
  • 「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;
    }
    
  • 相关阅读:
    Ribbon【负载均衡策略】
    Ribbon【入门】
    Mysql主从复制原理及同步延迟问题
    JWT 身份认证优缺点分析以及常见问题解决方案
    Feign【token传递】
    Feign【首次请求失败】
    Feign【文件上传】
    Feign【替换默认的feign client】
    Feign【开启GIZP压缩】
    Feign【@FeignClient】
  • 原文地址:https://www.cnblogs.com/asuldb/p/10392407.html
Copyright © 2011-2022 走看看