http://codeforces.com/problemset/problem/732/D
直接二分答案,check能否在x天内考完。
注意:二分边界,可以根据输入,求出能够复习的天数sum,考试天数M,因此 L = sum+M 否则超时
自己。puts("-1")记得return;
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int ed[111111];//Eaxm day 6 int nt[111111];//Need review time 7 int dead[111111];// Deadline - the Last Exam day 8 int inx[111111]; // if in the dead[] 9 int N,M; 10 bool check(int x) 11 { 12 memset(inx,0,sizeof(inx)); 13 int cnt = 0; 14 //找出每门课程在前x天 最后的考试时间 15 for (int i = 1; i <= x ; i++) 16 { 17 if (ed[i]!=0) 18 { 19 if (inx[ed[i]]==0) cnt++; 20 else dead[ inx[ed[i]] ] = 0; 21 dead[i] = ed[i]; 22 inx[ed[i]] = i; 23 } 24 else dead[i] = 0; 25 } 26 if ( cnt != M ) return false; 27 long long ht = 0 , ut = 0 ; 28 //扫一边1--x,对于每天i,拥有的复习时间ht。和需要的复习时间ut 始终应保持 ht >= ut 29 for (int i = 1; i <= x ; i++ ) 30 { 31 if (dead[i] == 0) ht++; 32 else 33 { 34 ut += nt[ dead[i] ] ; 35 } 36 if (ht < ut) return false; 37 } 38 return true; 39 } 40 int main() 41 { 42 //freopen("in.txt","r",stdin); 43 scanf("%d%d",&N,&M); 44 int sum = 0; 45 int flag = 1; 46 for (int i = 1; i<=N; i++) 47 { 48 scanf("%d",&ed[i]); 49 } 50 for (int i = 1 ; i<= M; i++) 51 { 52 scanf("%d",&nt[i]); 53 sum+=nt[i]; 54 if (sum > N-M) flag = 0; 55 } 56 if (flag == 0) {puts("-1");return 0;} 57 int l = M + sum; 58 int r = N; 59 int ans = -1; 60 while (l<=r) 61 { 62 int mid = ( l + r ) / 2 ; 63 if (check(mid)) 64 { 65 r = mid - 1; 66 ans = mid; 67 } 68 else l = l + 1; 69 } 70 cout << ans <<endl; 71 }
补充一份just_soso学长代码,用queue实现check()函数.
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define fst first 4 #define snd second 5 typedef long long ll; 6 typedef pair<ll, ll> pll; 7 const int maxn=100005; 8 ll n, m, d[maxn], a[maxn], sum; 9 stack<pll> day; 10 bool vis[maxn]; 11 bool check(ll mid) { 12 memset(vis, 0, sizeof vis); 13 vis[0]=true; 14 while (!day.empty()) 15 day.pop(); 16 int cnt=0; 17 for (int i=mid; i>=1; --i) { 18 if (vis[d[i]]) 19 continue; 20 vis[d[i]]=true; 21 day.push(pll(a[d[i]], i)); 22 ++cnt; 23 } 24 if (cnt<m) 25 return false; 26 ll tmp=0; 27 while (!day.empty()) { 28 pll t=day.top(); 29 day.pop(); 30 tmp+=t.fst+1LL; 31 if (tmp>t.snd) 32 return false; 33 } 34 return true; 35 } 36 int main() 37 { 38 //freopen("in.txt", "r", stdin); 39 while (scanf("%I64d%I64d", &n, &m)==2) { 40 sum=0; 41 for (int i=1; i<=n; ++i) 42 scanf("%I64d", &d[i]); 43 for (int i=1; i<=m; ++i) { 44 scanf("%I64d", &a[i]); 45 sum+=a[i]; 46 } 47 ll left=m+sum, right=n, res=-1; 48 while (left<=right) { 49 ll mid=(left+right)>>1; 50 bool flag=check(mid); 51 if (flag) { 52 res=mid; 53 right=mid-1; 54 } else 55 left=mid+1; 56 } 57 printf("%I64d ", res); 58 } 59 return 0; 60 }