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

通道

思路:先求一下从第一位开始的到第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;
}

时间: 2024-10-11 21:26:14

【瞎搞】 51nod 1065 最小正字段和的相关文章

51nod 1065 最小正子段和

题目链接:51nod 1065 最小正子段和 房教说用前缀和做,然后看了别人博客懂了后就感觉,这个真有意思... 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N = 50001; 6 const int inf = 0x3f3f3f3f; 7 pair<long long, int> sum[N]; 8 int

51nod 1065 最小正子段和 (贪心)

题目:传送门. 题意:中文题. 题解:求前缀和,并且标记每个数的下标,按照前缀和大小进行从小到大排序.随后进行遍历,如果满足下标data[i-1].id<data[i].id&&data[i-1].val<data[i].val:就更新最小值,因为是相近的,所以已经是最小值候选了,其余的绝对不可能了.那么为什么只考虑相邻的呢?因为如果A到B不能形成队列,A到C形成队列了,那么B到C一定是比A到C的数值更小,而且还一定能够形成队列(A与B不能形成队列,说明posA>posB

1065 最小正子段和 二分答案 + 判定

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1065 我的思路比较笨,我是直接二分那个答案mid 然后进行一次O(nlogn)的判定,如果能找到一个区间的和比mid小的,(当然这个区间的和也是要大于0),那就return true 进行判断如下: 处理出前缀和dp[i],对于每一个i 目标是:在前i - 1个中,查看是否有这样的一个x,使得,dp[i] - x    <=   mid,&& dp[i] -

AC日记——最小正子段和 51nod 1065

最小正子段和 思路: 找最小的大于0的sum[j]-sum[i](j>i): 高级数据结构(splay)水过: 来,上代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 50005 #define ll long long #define INF 0x7fffffff str

Codeforces 433C. Ryouko&#39;s Memory Note (中位数,瞎搞,思维)

题目链接: http://codeforces.com/problemset/problem/433/C 题意: 给你一堆数字,允许你修改相同的数字成为别的数字,也可以修改成自己,问你修改后相邻数字的距离的绝对值的和最小是多少. 思路: 首先明确一个结论,一个数轴上一些点,要求一个与他们距离之和尽量小的点,那么这个点就是这些点的中位数,即排序后位于中间的数. 这题的思路是把每一个数的与之相邻的保存下来,为了方便,可以用vector数组.然后为了使得距离之和最短,要取中位数.在一串数字中,距所有数

【瞎搞】HDU 4968 Improving the GPA

枚举一种GPA有多少个 总分1加上该GPA的最小分数 总分2加上该GPA的最大分数 若总分1<=输入分数×n<=总分2 则可以在枚举的状态达到目标分数 #include <stdio.h> #include <string.h> #include <math.h> #include <string> #include <algorithm> using namespace std; #define IN freopen ("

HDU 4940(杭电多校#7 1006) Destroy Transportation system(瞎搞)

题目地址:HDU 4940 当时这个题一看就看出来了是网络流的最小割,然后就一直在想建图..然后突然发现,应该要让T集合的数目最少,不然只要有两个,那这两个的每一个都可以跑到S集合,使得T集合变小.那就只能是1个了.然后..枚举就好了..但是虽然觉得这么做肯定没错..但是不敢敲..因为当时都3个小时了才只有10个队过了...后来又想了几遍后觉得这样没错,就写完交上了.果然AC... 代码如下: #include <iostream> #include <cstdio> #inclu

HDU 4915 Parenthese sequence(瞎搞题)

从左向右扫一遍左括号的最大值,与最小值. 从右向左扫一遍右括号的最大值,与最小值. 比较最大值中的最小数与最小中的最大数看能否有交集,0个,1个或者多个. Parenthese sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 301    Accepted Submission(s): 129 Problem De

HDU5532 Almost Sorted Array(最长上升子序列 or 瞎搞个做差的数组)

题目链接:点我 题意:给定一个序列,询问是否能删除一个数让它成为非递减或者非递增的序列. 比如说 删除后的序列是1 3 3 5 或者5 3 3 1 或者1 3 5 或者5 3 1 都可以.只要满足删掉某个数,构成非递减或者非递增,就输出YES,如果不能就输出NO 正解(LIS求最长上升子序列): 正着来一遍,反着来一遍 注意要用upper_bound即可: 代码: #include<bits/stdc++.h> using namespace std; int Maxlen(int a[],i