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

Codeforces732D心得

时间:2017-11-21 23:42:37      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:推广   print   about   dex   void   imu   oid   sed   params   

题目描述:

Vasiliy has an exam period which will continue for n days. He has to pass exams on m subjects. Subjects are numbered from 1 to m.

About every day we know exam for which one of m subjects can be passed on that day. Perhaps, some day you can‘t pass any exam. It is not allowed to pass more than one exam on any day.

On each day Vasiliy can either pass the exam of that day (it takes the whole day) or prepare all day for some exam or have a rest.

About each subject Vasiliy know a number ai — the number of days he should prepare to pass the exam number i. Vasiliy can switch subjects while preparing for exams, it is not necessary to prepare continuously during ai days for the exam number i. He can mix the order of preparation for exams in any way.

Your task is to determine the minimum number of days in which Vasiliy can pass all exams, or determine that it is impossible. Each exam should be passed exactly one time.

输入描述:

The first line contains two integers n and m (1?≤?n,?m?≤?105) — the number of days in the exam period and the number of subjects.

The second line contains n integers d1,?d2,?...,?dn (0?≤?di?≤?m), where di is the number of subject, the exam of which can be passed on the day number i. If di equals 0, it is not allowed to pass any exams on the day number i.

The third line contains m positive integers a1,?a2,?...,?am (1?≤?ai?≤?105), where ai is the number of days that are needed to prepare before passing the exam on the subject i.

输出描述:

Print one integer — the minimum number of days in which Vasiliy can pass all exams. If it is impossible, print -1.

输入样例:

7 2

0 1 0 2 1 0 2

2 1

输出样例:

5

题目解释:

  你有m门考试在m天之内要过,每一天要么为0,代表该天不能考试,只能准备,否则则为只能考的那一门考试的编号,代表该天只能考那一门考试,或者不考,拿来准备考试,而每一门考试都有需要准备的天数,只有准备了至少那么多天后考这门考试才能过。题目要求你输入考试的天数,考试门门数,每天可以考试的科目下标以及每一门考试需要准备的天数。你需要求出最早能过完所有考试的天数,或者输出-1代表这n天内不能过完这m门考试。

题目分析:

  题目要求求最早的能过完所有考试的天数,这是一个最值,因此,我们很容易的就可以想到二分,那么我们其实就应该先确定一个可以过完所有考试的天数,然后继续二分向前找尽量早的能过完所有考试的天数。很好,策略已经确定了,那么接下来我们需要解决的就是一个问题:怎么确定某一天能不能过完所有的考试,我们来看这样一个例子:

7 2

0 1 0 2 1 0 2

2 1

其中,第二行为每一天能考试的科目下标,第三行为每一门考试要过需要准备的天数。我们先在这n天内过完这些考试,其实最迟的就是在第n天过完所有考试,因此,我们需要从最后一天开始过考试,最后一天,能考试的科目为2,假设我们最后一天才过这门课,那么前面可以考这门考试的天都可以拿来准备,因此,序列变为0 1 0 0 1 0 2 ,0的天数都拿来准备考试,为了过第二门考试,前面一个0拿来准备该考试了,准备以后,都变为-1,表示该天已经准备考试了,不能再拿来准备其他考试,序列变为:-1 1 0 0 1 0 2接着,第二门考试已经过了,我们往前遍历,倒数第二天只能拿来准备,我们不理它,倒数第三天可以考第一门考试,我们再把倒数第三天以前可以考第一门考试的天数置0,代表可以拿来准备考试,序列变为:-1 0 0 0 1 0 2,而要过第一门考试,我们将前面0中的2个拿来准备第一门考试,序列变为:-1 -1 -1 0 1 0 2,到此,我们已经符合这n天过完所有考试。而这个方法可以推广到每一天:对于二分的每一天,我们都用此方法来判断该天内能否过完所有考试,如果能,继续二分向前查找尽可能早的能过完所有考试的天数,否则,我们二分向后查找能过完所有考试的天数,如果这n天斗不能,输出-1代表这n天不能过完所有考试。下面上代码:

#include <stdio.h>

#include <string.h>

#define N 100005

int n,m,d[N],a[N];

int Is[N];

int Can(int n)

{

  int i,sum = 0;

  memset(Is,0,sizeof(Is));

  for (i = n; i >= 1; i--)

  {

//将该天能考的考试之前能考的天数置为0 并拿出该门考试需要准备的天数flag置为1代表该门考试过了 用sum加上该天需要准备的天数

     if(d[i] != 0 && Is[d[i]] == 0)

    {

       Is[d[i]] = 1; sum += a[d[i]];

    }

//如果该门考试在后面已经过了,则sum减少,代表这一天不拿来准备

 

    else if(sum != 0)

   {

     sum--;

    }

  }

   for (i = 1; i <= m; i++)

   {

      if(!Is[i])

     {

         return 0;

     }

  }

    if(sum != 0)

   {

     return 0;

    }

//返回1代表该天之内可以过完所有考试

 

    return 1;

}

int main(void)

{

    int low,high,mid,i,j;

    scanf ("%d%d",&n,&m);

    for (i = 1; i <= n; i++)

    {

        scanf ("%d",&d[i]);

    }

    for (i = 1; i<= m; i++)

    {

        scanf ("%d",&a[i]);

    }

    low = 1;

    high = n;

 //二分查找符合能过完所有考试的最小天数

 

    while (low < high)

    {

        mid = low + (high -low) / 2;

        if(Can(mid) == 1)

        {

            high = mid;

        }

        else

        {

            low = mid + 1;

        }

    }

//判断剩下的那一天能都过完所有考试,如果能,它一定是最小的那一天

    if(Can(low))

    {

        printf ("%d\n",low);

    }

    else if(Can(high))

    {

        printf ("%d\n",high);

    }

    else

    {

        printf ("-1\n");

    }

    return 0;

}

 

 

Codeforces732D心得

标签:推广   print   about   dex   void   imu   oid   sed   params   

原文地址:http://www.cnblogs.com/Tang123456/p/7875540.html

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