UAPC 2011 G Everything Starts With Your Vote

問題

n個のキャラクターが居て、彼らの得票数は現在それぞれx[i]である。
この中でお気に入りのキャラクターがm個与えられる。
お気に入りのキャラクターにl票を好きなように投票して、k位以上のキャラクターがなるべく多くなるようにしたい。


k位以上になれるキャラクターの最大値を求めよ。

方針

何人がk位以上に入れるかについて二分探索。
m人がk位になるためには、お気に入りじゃないキャラクターのm-k+1位に勝つことが必要。
その票数を足してやれば、m人がk位になるための必要票数が求まる。

ソースコード

struct S{
  char s[11];
  int x;
  bool operator<(const S &r)const{
    if(x!=r.x)return x>r.x;
    return strcmp(s,r.s)<0;
  }
};
S chara[100000];
int n,m,k,l;

vector<S> like, dislike;
ll calc(int m){
  ll need=0;
  if(dislike.size()<k-m+1)return 0;
  rep(i,m){
    //cerr<<"hoge: "<<dislike[k-m].x-like[i].x<<endl;
    need+=max(0,dislike[k-m].x-like[i].x+
    (strcmp(dislike[k-m].s,like[i].s)<0));
  }
  //cerr<<"m: "<<m<<" need: "<<need<<endl;
  return need;
}

int main(){
  while(scanf("%d%d%d%d",&n,&m,&k,&l),n){
    set<string> names;
    rep(i,n)scanf("%s%d",chara[i].s,&chara[i].x);
    rep(i,m){
      char in[11]; scanf("%s",in);
      names.insert(string(in));
    }
    like.clear(); dislike.clear();
    rep(i,n){
      if(names.count(chara[i].s))like.pb(chara[i]);
      else dislike.pb(chara[i]);
    }
    sort(all(like)); sort(all(dislike));
    //rep(i,dislike.size())cerr<<dislike[i].s<<" "<<dislike[i].x<<endl;
    
    int lo=0, hi=min(m,k)+1, mid;
    while(lo+1<hi){
      mid=(lo+hi)/2;
      if(calc(mid)<=l)lo=mid; else hi=mid;
    }
    printf("%d\n",lo);
  }
  return 0;
}