読者です 読者をやめる 読者になる 読者になる

kanetaiの二次記憶装置

プログラミングに関するやってみた、調べた系のものをQitaに移して、それ以外をはてブでやる運用にしようと思います。http://qiita.com/kanetai

The Lonely Girl's Lie(AOJ No.0272)

リポジトリ

The Lonely Girl's Lie(AOJ No.0272)

N
a1 a2 ... aN
b1 b2 ... bN
が与えられる。
aiはAがもっているパケモンのレベルbiはBがもっているパケモンのレベルを示す。
パケモンを戦わせたとき、レベルが高い方が勝つ。同レベルなら引き分け。
お互いk匹パケモンを選んで1対1でk回戦したとき、Aの勝ち数が必ずk/2より大きくなるようなkの最小値を求める。
どう選んでも勝てない場合はNAと答える。
制約
1 ≤ N ≤ 40000
1 ≤ ai,bi ≤ 100000
1 ≤ k < N

アルゴリズム

お互いの最前手は強い順でk匹選んだ場合。
強い順にソートし、
kを増やしながら2分探索して
Aの勝ち数 = k - Bの勝ちor引き分け数
を求める。
境界条件を間違えないようにする。
k == NはNA

コード

Collections.reverseOrder()便利。プリミティブ型には使えないけど。
Memory Limit Exceededたくさん出した。
毎回配列を生成したり、コンパレータを渡しているのがまずいのかと思って直して提出してみたけど、
やっぱりMemory Limit Exceededじゃないか...(呆れ)
System.gc()を入れてとおりました。競技プログラミングでガーベジコレクションとか正気か?

import java.util.*;
public class aoj0272 {
    static final Scanner stdin = new Scanner(System.in);
    public static void main(String[] args) {
        while (true) {
            int n = stdin.nextInt();
            if (n == 0) break;
            System.gc();
            Integer[] a = new Integer[n], b = new Integer[n];
            for (int i = 0; i < n; ++i) a[i] = stdin.nextInt();
            for (int i = 0; i < n; ++i) b[i] = stdin.nextInt();
            Arrays.sort(a, Collections.reverseOrder());
            Arrays.sort(b, Collections.reverseOrder());
            int k = n;
            for (int i = 0, bNotFail = 0; i < n; ++i) {
                k = i+1;
                int pos = lowerBound(b, a[i]-1, Collections.reverseOrder())-1;
                if (bNotFail <= pos) ++bNotFail;
                if ((k - bNotFail) > k/2) break;
            }
            System.out.println(k < n ? k : "NA");
        }
    }
    public static <T> int lowerBound(T[] a, int fromIndex, int toIndex, T key, Comparator<? super T> c){
        int lb = fromIndex - 1, ub = toIndex;
        while(ub - lb > 1){          //rage of solution > 1
            int mid = (lb + ub) / 2, cmp = c.compare(a[mid], key);
            if( cmp >= 0 )   ub = mid;   //(lb,mid]
            else            lb = mid;   //(mid,ub]
        }
        return ub;                      //(lb, ub], ub = lb + 1 → [ub, ub+1)
    }
    public static <T> int lowerBound(T[] a, T key, Comparator<? super T> c){
		return lowerBound(a, 0, a.length, key, c);
	}
}