Codeforces #732D 二分 贪心

来源:互联网 发布:电脑地图软件 编辑:程序博客网 时间:2024/05/29 09:28

题目链接

题意:


给你n天和m课程,di表示这一天的状态,等于0说明可以复习课程或者休息,否则说明在这一天可以通过di课程。m个ai表示第i课程需要复习ai天,求最少通过所有课程的天数,若通过不了输出-1。


解析


二分可以通过的天数,然后判断在mid天数内,能否通过所有课程。judge时,从mid天开始到第一天:
1、daymid==0,找最近的课程给他复习。
2、daymid0,说明课程出现,若是第一次出现则记录下来;若不是则给最近的课程复习。


代码

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include <stack>using namespace std;const int maxn = 100000+10;const int inf = 0x3f3f3f3f;int n, m;int a[maxn];int vis[maxn];struct node{    int sb, cur;    node(){cur = 0;}}da[maxn];bool check(int day){    stack<node>s;    memset(vis, 0, sizeof(vis));    int res = 0;    for (int i=day; i>=1; i--)    {        if (da[i].sb != 0 && vis[da[i].sb] == 0){ //从最晚的课程,第一次遇到压入栈            da[i].cur = 0;            s.push(da[i]);            vis[da[i].sb] = 1;        }        else if ((da[i].sb == 0 || vis[da[i].sb] == 1) && !s.empty()) //为0或者课程不是第一次出现 取最近的课程给他安排复习        {            node now = s.top();            s.pop();            now.cur++;            if (now.cur == a[now.sb])                res++;            else                s.push(now);        }    }    if (res == m)        return true;    else        return false;}int main() {    scanf("%d%d", &n, &m);    for (int i=1; i<=n; i++)        scanf("%d", &da[i].sb);    for (int i=1; i<=m; i++)        scanf("%d", &a[i]);    int l=1, r=n;    int ans = -1;    while (l <= r){        int mid = (l+r)>>1;        if (check(mid) == true)            r = mid-1, ans = mid;        else            l = mid+1;    }    printf("%d\n", ans);    return 0;}
0 0