题目:
题解:
有趣的二分套贪心。
二分是学姐推荐题的时候说的,,如果自己瞎做不一定能想出来。。。。
二分通过考试的时间
check函数
考虑如果有一门课在i天可以考,在i+j天也可以考,那么就在i+j天考
证明:对于i+j以后的天数,由于这门课的复习和考试时间不变,无影响;
对于i+j天以前的天数,显然为其余的科目留下了更多的准备方案,更优;
依据这个思想,将数组倒序for一遍;
若某天的考试科目没有考过,压入栈中;
若某天的考试科目考过或不能考试,就用来准备栈顶科目(栈顶科目的考试时间早,需要优先准备)。
真的是随便贪心交了一下,,居然就过了???
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000+5000,M=100000+5000;
int S[M],ned[M],a[N],b[M];
bool is[M];
int cnt,tot,n,m,l,r;
void init(){
is[0]=1;
for(int i=1;i<=m;i++) {
ned[i]=-b[i];
is[i]=0;
}
tot=0;
cnt=0;
}
bool check(int x){
init();
for(int i=x;i>=1;i--){
if(!is[a[i]]) {
is[a[i]]=1;
S[++tot]=a[i];
continue;
}
ned[S[tot]]++;
if(ned[S[tot]]==0) tot--,cnt++;
if(tot==0&&cnt==m) return true;
}
return false;
}
int main(){
scanf("%d%d",&n,&m);
l=m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]),l+=b[i];
r=n+5;l-=1;
//printf("%d %d\n",l,r);
// int tmp;
// cin>>tmp;
// check(tmp);
while(r-l>1){
int mid=r+l>>1;
if(check(mid)) r=mid;
else l=mid;
}
if(r>n) printf("-1");
else printf("%d",r);
return 0;
}