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

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

时间:2017-01-26 23:09:16      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:oid   return   nod   ons   htm   names   stdin   ini   区间   

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] - x >= 1

二分找x,把前i - 1个东西压去set中,然后二分找x >= dp[i] - mid的那个x,判定即可。

 

技术分享
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 50000 + 20;
LL dp[maxn];
int n;
set<LL>ss;
bool check(LL val) {
    if (dp[1] <= val && dp[1] >= 1) return true;
    ss.clear();
    ss.insert(0);
    ss.insert(dp[1]);
    LL mx = max(0LL, dp[1]);
    for (int i = 2; i <= n; ++i) {
        LL x = dp[i] - val;
        if (mx < x) {
            mx = max(mx, dp[i]);
            ss.insert(dp[i]);
            continue;
        }
        set<LL> :: iterator it = ss.lower_bound(x);
        if (dp[i] - *it >= 1) return true;
        mx = max(mx, dp[i]);
        ss.insert(dp[i]);
    }
    return false;
}
void work() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        int x;
        scanf("%d", &x);
        dp[i] = dp[i - 1] + x;
    }
//    for (int i = 1; i <= n; ++i) {
//        cout << dp[i] << " ";
//    }
//    cout << endl;
    LL be = 1, en = 1e18L;
//    cout << check(1) << endl;
    while (be <= en) {
        LL mid = (be + en) >> 1;
        if (check(mid)) {
            en = mid - 1;
        } else be = mid + 1;
    }
//    cout << be << endl;
    printf("%lld\n", be);
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
View Code

 

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

标签:oid   return   nod   ons   htm   names   stdin   ini   区间   

原文地址:http://www.cnblogs.com/liuweimingcprogram/p/6352198.html

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