洛谷 P1115 最大子段和

目录:


题目:

传送门


分析:

超级水的贪心,直接 O ( n ) 过。
但小编就是想学下分治,所以介绍下分治的做法,顺便 m a r k e r 一下。
我们将整个数列最左设为 l ,最右设为 r ,中间位置设为 m i d
然后我们就可以发现,最大值的位置一定在三个地方:
1.从 l 一直加到 r —— O ( n )
2.从 l 一直加到 m i d (包含 m i d
3.从 m i d + 1 (包含 m i d + 1 )一直加到 r
第2、3点我们可以通过递归实现,所以整套题目的时间复杂度是: O ( n l o g n )


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#define LL long long
using namespace std;
const int fu=-99999999;
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
int max(int x,int y)
{
    return x>y? x:y;
}
int x[200001];
int n=read();
int rec(int l,int r)
{
    if(l==r) return x[l];
    int mid=(l+r)>>1;
    int sum=0,ml=fu,mr=fu;
    for(int i=mid;i>=l;i--)
      {
        sum+=x[i];
        ml=max(ml,sum);
      }
    sum=0;
    for(int i=mid+1;i<=r;i++)
      {
        sum+=x[i];
        mr=max(mr,sum);
      } 
    return max(max(rec(l,mid),rec(mid+1,r)),mr+ml);
}
int main()
{
    for(int i=1;i<=n;i++) x[i]=read();
    printf("%d",rec(1,n));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35786326/article/details/81668204