CodeForces - 732D Exams

Whiteying

2018-11-12 23:20:18

Personal

# B类 题外话:比赛的时候尝试过,但不是用的二分,用的暴力,但是没有TLE,是WA掉了,神奇。。。。 # 题目链接: https://vjudge.net/problem/CodeForces-732D # 题意: 你每天可以做三件事,考试、复习、或者休息。 每门课都有一个需要复习的天数,比如第i门课需要复习ai天,只有当你总共复习了ai天的第i门课,你才能在考试中通过这第i门课。当然,你也不用非得连续几天都复习一门课,可以穿插着复习,只要最后的天数满足就可以了。 为了尽早回家,你想计算出考完这m门课最少需要多少天?当然每门课都要考通过。要是怎么也不能全部通过,那就输出-1。 # 解题思路: 利用二分的思想,找出最优的天数. 假定出一个天数,然后从后往前遍历. 如果第一次遇到某种考试,那么就让你所有要复习的天数减去这门课要考的天数,同时把这种课标记掉. 如果你遍历到某一天是0或者是这一门已经被标记掉了,那么就让所有剩余的天数减一,因为你这一天拿来复习了. 当然,如果你剩余的天数小于你总的需要复习的天数,那么就返回错误. 遍历完成,看一下剩余的天数是否为0,如果为0就返回正确,否则返回错误. # AC代码: ```cpp #include<iostream> using namespace std; int n,m; int a[100005],b[100005]; bool judge(int time) { int sum=0; int vis[100005]={0}; for(int i=time;i>=1;i--) { if( a[i] && vis[a[i]]!=0 ) { sum+=b[a[i]]; vis[a[i]]=1; } else if(sum!=0) sum--; } for(int i=1;i<=m;i++) if(vis[i]==0) return false; if(sum!=0) return false; return true; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) scanf("%d",&b[i]); int left=1,right=n; while(left<right) { int middle=(left+right)/2; if(judge(middle)==false) left=middle+1; else right=middle; } if(judge(left)==true) printf("%d\n",left); else if(judge(right)==true) printf("%d\n",right); else printf("-1\n"); return 0; } ```