码迷,mamicode.com
首页 > 其他好文 > 详细

【瞎搞】 51nod 1065 最小正字段和

时间:2015-10-01 12:50:31      阅读:279      评论:0      收藏:0      [点我收藏+]

标签:

通道

思路:先求一下从第一位开始的到第i位的累加,
4,-1,5,-2,-1,2,6,-2 => 4 3 8 6 5 7 13 11

对这个累加的数列排个序,然后只要判断邻近的两个数是否可以组成序列,比如4和3就不可以,因为4 > 3而4对应下标为0,3对应为1。4和5就可以,然后相同的前缀和取id最小,一开始丢个(0,0)进去。

代码:

技术分享
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c = getchar() , c == EOF) return false;
    while(c != - && (c < 0 || c > 9)) c = getchar();
    sgn = (c == -) ? -1 : 1;
    ret = (c == -) ? 0 : (c - 0);
    while(c = getchar(), c >= 0 && c <= 9) ret = ret * 10 + (c - 0);
    ret *= sgn;
    return true;
}

const int MAX_N = 50007;
const ll inf = (ll)1e18 + 7;

int n;
ll a[MAX_N];
pair<ll,int> v[MAX_N], v1[MAX_N];

int main() {
    rd(n);
    for (int i = 1; i <= n; ++i) rd(a[i]);
    v[0] = make_pair(0, 0);
    ll sum = 0;
    for (int i = 1; i <= n; ++i) {
        sum += a[i];
        v[i] = make_pair(sum, i);
    }
    sort(v, v + n + 1);
    int cnt = 0, id = v[0].second;
    v1[cnt++] = v[0];
    bool update = false;
    for (int i = 1; i <= n; ++i) {
        if (v[i].first == v[i - 1].first) {
            id = min(id, v[i].second);
            update = true;
        } else {
            if (update) v1[cnt - 1].second = id;
            else v1[cnt++] = v[i];
            id = v[i].second;
            update = false;
        }
    }
    pair<ll,int> pre = v1[0];
    ll ans = inf;
    for (int i = 1; i < cnt; ++i) {
        ll val = v1[i].first - pre.first;
        if (val > 0 && v1[i].second > pre.second) {
            ans = min(ans, val);
        }
        pre = v1[i];
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

 

【瞎搞】 51nod 1065 最小正字段和

标签:

原文地址:http://www.cnblogs.com/Rojo/p/4850880.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!