zoukankan      html  css  js  c++  java
  • 题解 CF846C Four Segments

    题意

    给定长度为n的序列a,求出三个点i,j,k(0<=i<=j<=k<=n),使得a[1]+...+a[i]-a[i+1]-...-a[j]+a[j+1]+...+a[k]-a[k+1]-...-a[n]最大

    思路

    最开始没想出来,然后看了题解

    先对序列求前缀和,设为(sum)

    那么最大值为(max{ sum_i-(sum_j-sum_i)+(sum_k-sum_j)-(sum_n-sum_k)})

    化简后就是求(max{sum_i+sum_k-sum_j})(i,j,k)的位置

    题解里面是枚举(j),然后再(O(n))扫前缀和求(sum_i,sum_k)的最大值

    (j)是逐渐变化的,我们可以用单调队列来维护(sum_k)的最大值,至于(sum_i)的最大值直接维护即可

    时间复杂度$ O(n)$

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int n,ansi,ansj,ansk,l=1,r=0;
    int a[5010],q[5010];
    signed main(){
    	long long ans=(-(1ll<<62));
    	scanf("%lld",&n);
    	for(int i=1;i<=n;i++){scanf("%lld",&a[i]);a[i]+=a[i-1];}
    	for(int i=1;i<=n;i++){
    		while(l<=r && a[i]>a[q[r]])r--;
    		q[++r]=i;
      }
    	int ki=0,kk,sum1,sum2,sum3;
    	for(int j=0;j<=n;j++){
    		if(q[l]<j)l++;kk=q[l];
    		if(a[ki]<a[j])ki=j;
    		if(a[kk]+a[ki]-a[j]>ans)ans=a[kk]+a[ki]-a[j],ansi=ki,ansj=j,ansk=kk;
    	}
    	printf("%lld %lld %lld
    ",ansi,ansj,ansk);
    	return 0;
    }
    
  • 相关阅读:
    淘宝技术
    GridView使用
    仿QQ底部切换(Fragment + Radio)
    ViewPage+Fragment(仿微信切换带通知)
    PopupWindow --- 弹出底部窗体
    Activity--弹出底部窗口
    eclipse code style
    抽象类和接口
    java.lang.IllegalStateException: Not connected to server
    android真机 adb调试sqlite数据库
  • 原文地址:https://www.cnblogs.com/fpjo/p/13966010.html
Copyright © 2011-2022 走看看