Codeforces Round #377 (Div. 2) D. Exams 貪心+二分

題意: 給出長度爲n的數組d,di 表示在第i天的活動,di 表示可以進行編號爲di 的科目的考試或者複習,di =0的時候只能複習.
再給出長度爲m的數組a,ai 表示第i科所需要的複習時間.問最少需要幾天能把所有科目pass(達到複習所需天數即可pass).


思路:顯然至少需要m+mi=1ai 天 , 二分答案L=m+mi=1ai , R=n.
check(x)函數,檢查前x天能否pass所有科目,記錄這x天中各科目考試的最後期限,按照最後期限依次分配複習天數.


Code:

     File Name: 732D.cpp
     ID: PhyCode
     PROG: 
     LANG: C++ 
     Mail: 763315163@qq.com 
     Created Time: 20161018日 星期二 101922************************************************************************/
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
int d[MAX],a[MAX],p[MAX],s[MAX],n,m;
struct Node{
  int x,y,z;
  Node(int xx,int yy,int zz): x(xx),y(yy),z(zz){}
  bool operator <(const Node &a) const {
    return z>a.z;
  }
};
bool check(int x){
  priority_queue<Node>pq;
  memset(p,0,sizeof p);
  memset(s,0,sizeof s);
  for (int i=x; i>=1; --i){
    if (d[i]&&!p[d[i]]){
      p[d[i]]=i;
      pq.push(Node(a[d[i]],d[i],p[d[i]]));
    }
  }
  int sub=pq.size();
  if (sub<m)return 1;
  for (int i=1; i<=x; ++i){
    int c=pq.top().y;
    if (d[i]&&p[d[i]]==i){
      if (s[d[i]]<a[d[i]]){
        return 1;
      }
    }
    else{
      s[c]++;
      if (s[c]==a[c])pq.pop();
    }
  }
  sub=pq.size();
  if (sub==0)return 0;
}
int main(){
  int l,r,mid;
  scanf("%d%d",&n,&m);
  for (int i=1; i<=n; ++i){
    scanf("%d",d+i);
  }
  l=m,r=n;
  for (int i=1; i<=m; ++i){
    scanf("%d",a+i);
    l+=a[i];
  }
  while (l<r+1){
    mid=(l+r)/2;
    if (check(mid)) l=mid+1;
    else r=mid-1;
  }
  if (l>=n+1)printf("-1\n");
  else printf("%d\n",l);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章