Problem:
微生物実験(Bug Party)

あなたはJust Odd Inventions 社を知っているだろうか? この会社の業務は「ただ奇妙な発明(just odd inventions)」をすることである．ここでは略してJOI 社と呼ぶ．

JOI 社では多くの微生物を1 つのシャーレに生きたまま閉じ込める研究をしている．調査対象の微生物はN 匹存在し，1, 2, ... , N という番号がついている．各微生物はシャーレに閉じ込められると，foo (fatally odd object) と呼ばれる有害物質を一瞬のうちにシャーレ内に放出する．各微生物が放出するfoo の量は知られている．シャーレに閉じ込められた全微生物が放出したfoo はシャーレ内の各微生物が均等に摂取する．各微生物のfoo 許容量は知られており，この量を超えてfoo を摂取すると微生物は死んでしまう．

微生物i のfoo 放出量はai ミリグラム，foo 許容量はbi ミリグラムである．すなわち，シャーレに微生物i1, i2, ... , ik を閉じ込めたとき，シャーレ内の各微生物はそれぞれ(ai1 + ai2 + ... + aik)/k ミリグラムのfoo を摂取し，シャーレ内の微生物i は，この摂取量がbi より大きいと死んでしまう．

JOI 社からの委託により，あなたは出来るだけ多くの微生物をシャーレに生きたまま閉じ込めなければならない．ただし，微生物の死骸はシャーレ内の環境に悪影響を及ぼすため，シャーレ内のどの微生物もfoo の摂取で死んではならない．

なお，JOI 社が「ただ奇妙な発明」をすることでどうやって利益を得ているかは，今もって謎であり，JOI社内でも社長以外の誰も知らない．

課題

調査対象の微生物数と，各微生物のfoo 放出量とfoo 許容量が与えられたとき，1 つのシャーレに閉じ込めることができる微生物数の最大値を求めるプログラムを作成せよ．

制限

1 ≤ N ≤ 300000 = 3 × 105    調査対象の微生物の数

1 ≤ ai ≤ 100000 = 105    微生物i のfoo 放出量(ミリグラム)

1 ≤ bi ≤ 100000 = 105    微生物i のfoo 許容量(ミリグラム)

入力

標準入力から以下の入力を読み込め．

1 行目には整数N が書かれており，調査対象の微生物がN 匹存在することを表す．

続くN 行には各微生物の情報が書かれている．i + 1 行目(1 ≤ i ≤ N) には，正整数 ai, bi が空白を区切りとして書かれており，微生物i のfoo 放出量がai ミリグラムでfoo 許容量がbi ミリグラムであることを表す.

出力

標準出力に，1 つのシャーレに閉じ込めることができる微生物数の最大値を1 行で出力せよ．

注意

この問題では，扱う整数の範囲が32 ビットに収まらない可能性があることに注意せよ．

採点基準

採点用データのうち，配点の30% については，N ≤ 1000 を満たす．

入出力の例

入力例

6
12 8
5 9
2 4
10 12
6 7
13 9

出力例

3

この例では，微生物2, 4, 5 をシャーレに入れれば，放出されるfoo の合計量は5 + 10 + 6 = 21 ミリグラムとなり，それぞれの微生物が摂取するfoo の量は21/3 = 7 ミリグラムとなる．微生物2, 4, 5 のfoo 許容量はそれぞれ9, 12, 7 ミリグラムなので，シャーレ内のどの微生物も死なない．また，4 匹以上の微生物をどの微生物も死なないようにシャーレに入れることはできない．

問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in JAVA (judge verdict: Time Limit Exceeded)

import java.io.InputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.math.BigInteger;

public class Main{

static PrintWriter out;
static InputReader ir;

static void solve(){
 int n=ir.nextInt();
 int[][] bs=new int[n][];
 for(int i=0;i<n;i++) bs[i]=ir.nextIntArray(2);
 Arrays.sort(bs,new Comparator<int[]>(){
  public int compare(int[] a,int[] b){
   return Integer.compare(a[1],b[1]);
  }
 });
 int[][] f=new int[n][];
 for(int i=0;i<n;i++) f[i]=new int[]{bs[i][0],i};
 Arrays.sort(f,new Comparator<int[]>(){
  public int compare(int[] a,int[] b){
   return Integer.compare(a[0],b[0]);
  }
 });
 int lb=0,ub=n+1;
 while(ub-lb>1){
  int mid=(lb+ub)>>>1;
  if(ok(mid,bs,f)) lb=mid;
  else ub=mid;
 }
 out.println(lb);
}

public static boolean ok(int m,int[][] bs,int[][] f){
 int n=bs.length;
 for(int i=0;i<n;i++){
  int ct=0;
  long tot=0;
  for(int j=0;j<n&&ct<m;j++){
   if(f[j][1]>=i){
    ct++;
    tot+=(long)f[j][0];
   }
  }
  if(ct==m&&tot<=(long)bs[i][1]*(long)m) return true;
 }
 return false;
}

public static void main(String[] args) throws Exception{
 ir=new InputReader(System.in);
 out=new PrintWriter(System.out);
 solve();
 out.flush();
}

static class InputReader {
 private InputStream in;
 private byte[] buffer=new byte[1024];
 private int curbuf;
 private int lenbuf;

 public InputReader(InputStream in) {this.in=in; this.curbuf=this.lenbuf=0;}
 
 public boolean hasNextByte() {
  if(curbuf>=lenbuf){
   curbuf= 0;
   try{
    lenbuf=in.read(buffer);
   }catch(IOException e) {
    throw new InputMismatchException();
   }
   if(lenbuf<=0) return false;
  }
  return true;
 }

 private int readByte(){if(hasNextByte()) return buffer[curbuf++]; else return -1;}
 
 private boolean isSpaceChar(int c){return !(c>=33&&c<=126);}
 
 private void skip(){while(hasNextByte()&&isSpaceChar(buffer[curbuf])) curbuf++;}
 
 public boolean hasNext(){skip(); return hasNextByte();}
 
 public String next(){
  if(!hasNext()) throw new NoSuchElementException();
  StringBuilder sb=new StringBuilder();
  int b=readByte();
  while(!isSpaceChar(b)){
   sb.appendCodePoint(b);
   b=readByte();
  }
  return sb.toString();
 }
 
 public int nextInt() {
  if(!hasNext()) throw new NoSuchElementException();
  int c=readByte();
  while (isSpaceChar(c)) c=readByte();
  boolean minus=false;
  if (c=='-') {
   minus=true;
   c=readByte();
  }
  int res=0;
  do{
   if(c<'0'||c>'9') throw new InputMismatchException();
   res=res*10+c-'0';
   c=readByte();
  }while(!isSpaceChar(c));
  return (minus)?-res:res;
 }
 
 public long nextLong() {
  if(!hasNext()) throw new NoSuchElementException();
  int c=readByte();
  while (isSpaceChar(c)) c=readByte();
  boolean minus=false;
  if (c=='-') {
   minus=true;
   c=readByte();
  }
  long res = 0;
  do{
   if(c<'0'||c>'9') throw new InputMismatchException();
   res=res*10+c-'0';
   c=readByte();
  }while(!isSpaceChar(c));
  return (minus)?-res:res;
 }

 public double nextDouble(){return Double.parseDouble(next());}

 public int[] nextIntArray(int n){
  int[] a=new int[n];
  for(int i=0;i<n;i++) a[i]=nextInt();
  return a;
 }

 public long[] nextLongArray(int n){
  long[] a=new long[n];
  for(int i=0;i<n;i++) a[i]=nextLong();
  return a;
 }

 public char[][] nextCharMap(int n,int m){
  char[][] map=new char[n][m];
  for(int i=0;i<n;i++) map[i]=next().toCharArray();
  return map;
 }
}
}