• 最小正子段和(前缀和+思维)


    最小正子段和

    基准时间限制:1 秒 空间限制:131072 KB 

    N个整数组成的序列a[1],a[2],a[3],…,a[n],从中选出一个子序列(a[i],a[i+1],…a[j]),使这个子序列的和>0,并且这个和是所有和>0的子序列中最小的。
    例如:4,-1,5,-2,-1,2,6,-2。-1,5,-2,-1,序列和为1,是最小的。
     
    Input
    第1行:整数序列的长度N(2 <= N <= 50000)
    第2 - N+1行:N个整数
    Output
    输出最小正子段和。
    Input示例
    8
    4
    -1
    5
    -2
    -1
    2
    6
    -2
    Output示例
    1

    分析:最近打牛客网的练习赛碰到一个和这个有点关系的题目,只能想到前缀和,后面就没了思路,队友告诉我和这个有点像,所以决定写一下,觉得写过的很多类似的题;
    N的取值范围为2 <= N <= 50000,所以暴力肯定会超时,所以我们用前缀和!但不是一般的前缀和,我们定义一个结构体,一个变量用来存储前缀和,一个变量用来存储下标,按前缀和排序,后面的比较就是个思维了!仔细想想,排序后,一个数字只有和它相邻数的差或者它本身为最小值,代码还是很好写的!
    AC代码:
    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define N 50050
    typedef long long ll;
    using namespace std;
    struct point
    {
        ll w;
        int v;
    }b[N];
    int a[N];
    bool cmp(point x,point y)
    {
        return x.w<y.w;
    }
    int main()
    {
        int n;
        cin>>n;
        for (int i=1;i<=n;i++)
        cin>>a[i];
        b[1].w=a[1];
        for (int i=2;i<=n;i++)
        {
            b[i].w=b[i-1].w+a[i];
            b[i].v=i;
        }
        sort(b+1,b+1+n,cmp);
        ll ans;
        if (b[1].w>0)  ans=b[1].w;
        else ans=99999999;
        for (int i=2;i<=n;i++)
        {
            if (b[i].w>0&&b[i].w<ans)
              ans=b[i].w;
            if (b[i].w>b[i-1].w&&b[i].v>b[i-1].v&&(b[i].w-b[i-1].w<ans))
              ans=b[i].w-b[i-1].w;
        }
        cout << ans << endl;
        return 0;
    }
     
  • 相关阅读:
    JDom写入XML例子
    hdu 2549
    hdu 1328
    hdu 1334
    hdu 2547
    hdu 2374
    hdu 2550
    hdu 1335
    hdu 2548
    hdu 1722
  • 原文地址:https://www.cnblogs.com/lisijie/p/8362672.html
Copyright © 2020-2023  润新知