CF732D Exams 二分 贪心
Posted jackpei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF732D Exams 二分 贪心相关的知识,希望对你有一定的参考价值。
思路:二分+贪心
提交次数:10次以上
错因:刚开始以为二分(边界,$+1or-1$)写错了,调了半天,后来才发现是$ck()$写错了。开始只判了最后是否小于零,而应该中间一旦小于零就$return\space false$
题解:
二分天数(单调性显然)。
$ck(int x)$: 首先$x$天内必须包含所有科目;然后贪心的考每一科的最后一次试(倒着扫一遍);维护一个剩余天数$cnt$,遇到空闲时间或不是最后本科目的一次考试就$++$,否则$-=$本科考试所需的复习天数;一旦$cnt<0$,直接$return\space false$;最后$return\space cnt>=0$。
代码:
#include<cstdio> #include<iostream> #include<cstring> using namespace std; //你弱,有什么资格休息 #define ull unsigned long long #define ll long long #define R register ll #define pause (for(R i=1;i<=10000000000;++i)) #define In freopen("NOIPAK++.in","r",stdin) #define Out freopen("out.out","w",stdout) namespace Fread static char B[1<<15],*S=B,*D=B; #ifndef JACK #define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++) #endif inline int g() R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch==‘-‘?-1:fix; if(ch==EOF) return EOF; do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix; inline bool isempty(const char& ch) return (ch<=36||ch>=127); inline void gs(char* s) register char ch; while(isempty(ch=getchar())); do *s++=ch; while(!isempty(ch=getchar())); using Fread::g; using Fread::gs; namespace Luitaryi const int N=1e+5+10; int n,m,ans=-1,cnt; int a[N],w[N]; bool vis[N],flg[N]; inline bool ck(int x) R ret=0,tmp=m; memset(vis,0,sizeof(vis)); memset(flg,0,sizeof(flg)); for(R i=x;i>=1&&tmp;--i) if(a[i]&&!vis[a[i]]) vis[a[i]]=true,flg[i]=true,--tmp; if(tmp!=0) return false; for(R i=1;i<=x;++i) if(a[i]!=0&&flg[i]) ret-=w[a[i]]; else ++ret; if(ret<0) return false; return ret>=0; inline void main() n=g(),m=g(); for(R i=1;i<=n;++i) a[i]=g(); for(R i=1;i<=m;++i) w[i]=g(); R l=m,r=n+1; while(l<r) R md=l+r>>1; if(ck(md)) r=md; else l=md+1; printf("%d\n",l==n+1?-1:l); signed main() Luitaryi::main(); return 0;
2019.07.14
以上是关于CF732D Exams 二分 贪心的主要内容,如果未能解决你的问题,请参考以下文章