jzoj1481. 偷懒的西西

123 篇文章 0 订阅
37 篇文章 0 订阅

Description


高三数学作业总共有n道题目要写(其实是抄),编号1..n,抄每道题所花时间不一样,抄第i题要花a[i]分钟。由于西西还要准备NOIP,显然不能成天做数学作业。所以西西决定只用不超过t分钟时间抄这个,因此必然有空着的题。每道题要么不写,要么抄完,不能写一半。一段连续的空题称为一个空题段,它的长度就是所包含的题目数。这样应付自然会引起数学老师的愤怒。数学老师发怒的程度(简称发怒度)等于最长的空题段长度。
现在,西西想知道他在这t分钟内写哪些题,才能够尽量降低数学老师的发怒度。由于西西很聪明,你只要告诉他发怒度的数值就可以了,不需输出方案。(Someone:那么西西怎么不自己写程序?西西:我还在抄别的科目的作业……)

Input


第一行为两个整数n,t,代表共有n道题目,t分钟时间。
以下一行,为n个整数,依次为a[1], a[2],… a[n],意义如上所述。

Output


仅一行,一个整数w,为最低的发怒度。

Data Constraint

Hint


60%数据 n<=2000
100%数据 0

Solution


签到题。我们可以二分一个最大连续空段,这样就变成了一个最多隔mid个不选的最小方案,f[i]=min{f[j]}+t[i] (i-mid-1<=j

Code


#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define max(x, y) ((x)>(y)?(x):(y))
#define min(x, y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<(0)?(-(x)):(x))
#define INF 0x3f3f3f3f
#define N 100001
#define E 1001
#define L 1001
int queue[N], f[N], t[N];
inline int read() {
    int x = 0, v = 1; char ch = getchar();
    for(; ch<'0'||ch>'9'; v=(ch=='-')?(-1):(v),ch=getchar());
    for(; ch<='9'&&ch>='0'; (x*=10)+=ch-'0',ch=getchar());
    return x * v;
}
inline bool check(int n, int m, int mid) {
    fill(f, 0);
    fill(queue, 0);
    int head = 0;
    int tail = 0;
    queue[tail] = 0;
    rep(i, 1, n) {
        while (queue[head] < i - mid - 1 && head <= tail) {
            head += 1;
        }
        f[i] = f[queue[head]] + t[i];
        while (f[queue[tail]] > f[i] && head <= tail) {
            tail -= 1;
        }
        queue[++ tail] = i;
    }
    int ans = INF;
    rep(i, n - mid, n) {
        ans = min(ans, f[i]);
    }
    return ans <= m;
}
int main(void) {
    int n = read();
    int m = read();
    rep(i, 1, n) {
        t[i] = read();
    }
    int l = 0;
    int r = n;
    int bobo = 0;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (check(n, m, mid)) {
            r = mid - 1;
            bobo = mid;
        } else {
            l = mid + 1;
        }
    }
    printf("%d\n", bobo);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值