Codeforces 893 D Credit Card 贪心 思维

  题目链接: http://codeforces.com/contest/893/problem/D

  题目描述: 每天晚上一个数值a,如果a>0表示今天收入a元,<0表示亏损a元,=0表示去检验自己的卡。每天早上(在前者之前)可以去充卡,可以随便充,但是充完之后不能大于上限d。每一次去查卡的时候,卡上的钱不能是个负数,任何时刻如果卡上的钱大于d了就视为不合法,直接输出-1。问最少充几次卡可以保证n天完全合法。

   解题思路: 一开始自己是知道只在查卡的时候充卡就可以了, 然后我是找到与(d相近的s)最小距离的那个下标, 然后0的时候加上去, 在第20组测试样例的时候T掉了, 然后这道题就弃了, 看了题解才知道只需要维护两个区间, 一个是剩余最大, 一个是最小

  我的超时的原因是我算清了每一步都需要加上多少为了取得这个值复杂度加上了O(n) , 所以其实维护的这个区间的作用就是我使得每一次查卡充卡的时候都冲到了d, 同时又记录了如果我不需要充卡的时候会不会超过d, 这样在每次充卡的时候在++ cnt就算出了答案

  代码: 

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <list>
#include <iterator>
#include <cmath>
#include <cstring>
using namespace std;

const int maxn = 1e5+10;
int a[maxn];
const int INF = 0x3fffffff;
int n, d;

int find_index(int s, int id, int & min_value) {
    int min_d = INF;
    int ret = -1;
    for(int i = id+1; i <= n; i++) {
        s += a[i];
        if(d-s < min_d) {
            min_d = d-s;
            ret = i;
        }
    }
    min_value = min_d;
    return ret;
}

int main() {
    //freopen("in.txt", "r", stdin);    
    scanf("%d%d", &n, &d);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    int s = 0;
    for(int i = 1; i <= n; i++) {
        s += a[i];
        if(s > d) {
            printf("-1\n");
            return 0;
        }
    }
    s = 0;
    int cnt = 0;
    int res = 0;
    while(cnt < n) {
        int pre_cnt = cnt+1;
        int min_value;
        cnt = find_index(s, cnt, min_value);
        int flag = 1;
        for(int i = pre_cnt; i <= cnt; i++) {
            s += a[i];
            if(a[i] == 0 && s < 0 && flag == 1) {
                s += min_value; 
                flag = 0;
                res ++;
            }
            if(a[i] == 0 && s < 0 && flag == 0 ) {
                printf("-1\n");
                return 0;
            }
        }
    }
    printf("%d\n", res);            
    return 0;
}
My TLE code
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <list>
#include <iterator>
#include <cmath>
#include <cstring>
using namespace std;

const int maxn = 1e5+10;
int a[maxn];
const int INF = 0x3fffffff;
int n, d;

int main() {
    scanf("%d%d", &n, &d);
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    int flag = 1;
    int top, bottom;
    int res = 0;
    top = bottom = 0;
    for(int i = 0; i < n; i++) {
        if(a[i] == 0) {
            if(top < 0) {
                res++;
                top = d;            
            }
            bottom = max(0, bottom);
        }
        else {
            top += a[i];
               bottom += a[i];
            top = min(top, d);
            if(bottom > d) {
                flag = -1;
                break;
            }
        }
    }
    if(flag == 1) {
        printf("%d\n", res);
    }
    else {
        printf("-1\n");
    }
    return 0;
}
View Code

  思考: 自己考虑问题还是不够全面 啊, 💩

posted on 2017-11-28 18:07  FriskyPuppy  阅读(260)  评论(0编辑  收藏  举报

导航