• 51nod1065(set.upper_bound()/sort)


    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1065

    题意:中文题诶~

    思路:

    解法1:set容器,将所有前缀和存储到set和sum数组里,再用set.upper_bound()查找sum[i]后面第一个大于sum[i]的元素,那么他们的差就是第i个元素开头的最小正子段和.然后再将sum[i]从set里面删除,不然会影响后面的查询嘛.遍历所有i就得到我们要的答案啦;

    代码:

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 #define MAXN 50010
     4 using namespace std;
     5 
     6 const int inf=0x3f3f3f3f;
     7 ll sum[MAXN];
     8 set<ll> st;
     9 
    10 int main(void){
    11     int n;
    12     ll x, ans=inf;
    13     scanf("%d", &n);
    14     for(int i=1; i<=n; i++){
    15         scanf("%lld", &x);
    16         sum[i]=sum[i-1]+x;
    17         st.insert(sum[i]);
    18     }
    19     st.insert(0);
    20     set<ll>::iterator it;
    21     for(int i=0; i<n; i++){
    22         it=st.upper_bound(sum[i]);
    23         if(it!=st.end()){
    24             ans=min(ans, *it-sum[i]);
    25         }
    26         st.erase(sum[i]);
    27     }
    28     cout << ans << endl;
    29     return 0;
    30 }

    解法2:将前缀和及其下标存储到pair对组(结构题也行啦)里;再以前缀和为权值sort一下,那么我们不难想到如果p[j].first>p[i].first&&p[j].second>p[i].second --条件1 的话p[j].fisrt-p[i].first 就是一段和为正数的子段的和.又因为我们已经给p排过序了,所以i,j越接近,那么得到的子段和就越小,很自然我们会想到j=i+1的情况.问题是对于j=i+1的情况上述条件1一定满足么?或者说最优解一定是来自j=i+1的情况里么?

    答案是肯定的,并且我们不难证明它:我们假设排序后顺序为 i, k, j,i和j满足条件1,i和k 不满足条件1, 即:

    p[j].second>p[i].second,p[k].second<p[i].second, 所以有:p[j].second>p[k].second,很显然k和j满足条件1并且k和j能比i和j产生更优的解;

    所以我们只要考虑j=i+1的情况即可.

    此外我们还要注意两点:1.我们排序后得到是p[i+1].first>=p[i].first 而非 p[i+1].first>p[i].first;

               2.我们还要考虑p[i].first本身的值,即从第1个元素到第i个元素的和的情况

    代码:

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 #define MAXN 50010
     4 using namespace std;
     5 
     6 const int inf=0x3f3f3f3f;
     7 pair<ll, int> p[MAXN];
     8 
     9 int main(void){
    10     int n;
    11     ll x, ans=inf;
    12     scanf("%d", &n);
    13     for(int i=1; i<=n; i++){
    14         scanf("%lld", &x);
    15         p[i].first=p[i-1].first+x;
    16         p[i].second=i;
    17     }
    18     sort(p, p+n+1);
    19     for(int i=0; i<n; i++){
    20         if(p[i].first>0){
    21             ans=min(ans, p[i].first);
    22         }
    23         if(p[i+1].second>p[i].second&&p[i+1].first>p[i].first){
    24             ans=min(ans, p[i+1].first-p[i].first);
    25         }
    26     }
    27     cout << ans << endl;
    28     return 0;
    29 }
  • 相关阅读:
    vim高亮
    mengning
    4.4内核osal
    tmpvalgrind
    为什么引入协程
    alloc_call_show(转)
    TSAN
    如何查看哪些进程占用Buffer和Cache高(转)
    ASAN详解其他参考链接
    Linux系统与程序监控工具atop教程(转)
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6337236.html
Copyright © 2020-2023  润新知