拉胯的题解又来了:P1115

打个广告:

洛谷博客:文章列表 - JunhanWang 的博客 - 洛谷博客

CSDN:CSDN

----------------------------------------------一刀不怎么华丽的分割线--------------------------------------------------

题解正式开始: 首先,这道题第一思路就是枚举从 L到 R的最大和,代码大概是定义一个CNT,从1到i,循环从1到i,长度不断增加,再比较一下就好啦,大概是O(n²)级别的,会超一点点

还有,就可以分治,所谓分治就是“分而治之”,把一个大问题划分成小问题,可以练习P1010和P1024。

分治思路:首先,假定有区间l~r,其中间位置为mid,其最大子段为[i..j]。有三种情况

只需要分别求出三种情况下的值,取其最大的即可。

那么,只需递归求出即可。

上代码

#include<bits/stdc++.h>
int n , arr[200200]; 
const int minn = -19260817;  
int rec( int l , int r ) { 
    if ( l == r ) {   
        return arr[l];
    }
    int mid = ( l + r ) >> 1;  
    int sum = 0 , ret1 = minn , ret2 = minn; 
    for( int i = mid ; i >= l ; i-- ) {
        sum += arr[i];
        ret1 = Max( ret1 , sum );
    }  
    sum = 0;
    for( int i = mid+1 ; i <= r ; i++ ) {
        sum += arr[i];
        ret2 = Max( ret2 , sum );
    }  
}
int main() { 
    scanf("%d", &n );
    for( int i = 1 ; i <= n ; i++ ) {
        scanf("%d" , &arr[i] );
    }
    printf("%d" , rec(1 , n) ); 
    return 0;
}

其实,这道题还可以用贪心做。

方法如下:要不选,要不自己是一类 比如 -1 -2 9

-1要选自己,因为前面没有数

-2要选自己,因为前面的数,-1+-2=-3 小于-2

9要选自己,因为9>9-3

上代码:

#include<bits/stdc++.h>
using namespace std;
int n,j,sum,maxx;
int main(){         
    scanf("%d%d",&n,&maxx)
    while(--n)
    {
        scanf("%d",&j);
        sum=sum>0?sum:0;
        sum+=j;
        maxx=maxx>sum?max:sum;  //直接复制有惊喜呦
  }
    return (printf("%d",maxx));
 }

纯正的DP做法: 首先,通过题意,我们可以了解到:

f[i]=max(f[i-1]+n[i],n[i])

但是!

f[n]的值并不一定是最终结果

比如这个输入:

5 233 233 -666 1 1

如果直接输出f[n]的值,结果会是2,但是答案应该为466!

为什么?

因为若f[i]的值为负数,则f[i+1]的值就是n[i],而n[i]的值不一定比前面的最大字段和数大!

(或者n[i]为负数,则f[i]小于f[i-1]!)

所以,我们还要再用一个数从1到n再查找一次,才能找出最大数

代码:

#include<bits/stdc++.h>
using namespace std;
int n[200001],p,ans[200001]={0};
const int INF=0x3f3f3f3f;
int main()
{
    int sum=-INF;
    cin>>p;
    for(int i=0;i<p;i++)
    {
        cin>>n[i];
        ans[i]=max(ans[i-1]+n[i],n[i]);
        sum=max(sum,ans[i]);
    }
    cout<<sum;
}

好了,这道题就讲到这里,希望大家CSP_J/S能得到好分数.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值