1. 程式人生 > >codeforces 732D Exams 二分搜尋 貪心

codeforces 732D Exams 二分搜尋 貪心

D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output

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 a

i 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.

Input

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.

Output

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

Examples input
7 2
0 1 0 2 1 0 2
2 1
output
5
input
10 3
0 0 1 2 3 0 2 0 1 2
1 1 4
output
9
input
5 1
1 1 1 1 1
5
output
-1
Note

In the first example Vasiliy can behave as follows. On the first and the second day he can prepare for the exam number 1 and pass it on the fifth day, prepare for the exam number 2 on the third day and pass it on the fourth day.

In the second example Vasiliy should prepare for the exam number 3 during the first four days and pass it on the fifth day. Then on the sixth day he should prepare for the exam number 2 and then pass it on the seventh day. After that he needs to prepare for the exam number 1 on the eighth day and pass it on the ninth day.

In the third example Vasiliy can't pass the only exam because he hasn't anough time to prepare for it.

題意:

某人要考試 。。。幹。。。明天再寫。。。

繼續。。。某人要考試,現在總共有n天m門考試,在這n天中有幾天是可以考特定的科目的,題中的d陣列會給出

比如

0 0 1 2 3 0 2 0 1 2

表示在第3、9天可以考科目1。 4、7、10天可以考科目2.。。。標號為0的那天可以用來複習,如果不選擇當天考試的話那天也可以用來複習

但是每門考試都需要複習一定的天數ai才能考好,對複習天數的要求是不用連續,只要累計達到ai即可

主人公想花最少的天數每門都考好,求最少天數,如果根本不可能輸出-1

比賽的時候還以為是動態規劃什麼的。。。。因為時間剩不多了,越寫越覺得靠譜。。。然而寫到後面又越來越不靠譜。。。。。

居然是二分搜尋答案!真是沒有想到,我感覺這個能想到的話就是要先確定我們能判斷給在給定的這些考試要求的情況下t天是否可能完成要求。對於t可以確定其是否可能才能在1~n內做二分搜尋啊!

假定現在有t天,我感覺這個採取的策略就是貪心。。。雖然不知道是否合適這樣稱呼。肯定每門科目都參加最後的那一場,那麼前面就會有儘可能多的時間給自己複習,如果即使這樣還是不能複習完的話,就不可能啦

能夠確定t天能否達到要求後,就能在1~n天內二分了

說難也不難。。。加油啊!

程式碼:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <map>
#include <set>
using namespace std;
const int maxn = 1e5 +10;
int n,m,need;
int a[maxn],d[maxn];
bool Bsearch(int k){
    int i;
    bool vis[maxn]={false};
    memset(vis, false, sizeof(vis));
    int free = k-m,last = need;
    for(i=k;i>=1;i--){
        if(!d[i]||vis[d[i]]){
            free--;
            continue;
        }
        if(free>=last){
            vis[d[i]]=true;
            last -= a[d[i]];
        }else{
            return false;
        }
    }
    return (free==0);
}
int main(){
    int i,j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++){
        scanf("%d",&d[i]);
    }
    need=0;
    for(i=1;i<=m;i++){
        scanf("%d",&a[i]);
        need+=a[i];
    }
    int left=1,right=n,middle;
    while(left<right){
        middle =(left+right)/2;
        if(Bsearch(middle)){
            right = middle;
        }else{
            left = middle +1;
        }
    }
    if(Bsearch(right)){
        printf("%d\n",right);
    }else{
        printf("-1\n");
    }
}
//10 3
//0 0 1 2 3 0 2 0 1 2
//1 1 4