とりあえず言語はjavaを選択。下記のような方針でコードを書きました。
1. 商品の金額データを昇順にソートする。
2. ソート済みのデータに対して先頭と後尾から挟み撃ちで検索をかけ、指定されたキャンペーン金額以下の最大値を検索する。
計算量は1がN(O*logN)で2がO(N)。なので全体としてはN(O*logN)になります。
2の探索はbinary searchを利用すればもう少し早くなりそうですが、どのみち1のソートでO(N*logN)かかるので、手を抜きました。
実際に書いたコードは次のようになります。
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; public class Main { public static void quickSort(int[] arr, int left, int right){ if (left <= right) { int p = arr[(left+right) / 2]; int l = left; int r = right; while(l <= r) { while(arr[l] < p){ l++; } while(arr[r] > p){ r--; } if (l <= r) { int tmp = arr[l]; arr[l] = arr[r]; arr[r] = tmp; l++; r--; } } quickSort(arr, left, r); quickSort(arr, l, right); } } public static void main(String args[]){ try { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String nd[] = br.readLine().split(" "); int n = Integer.parseInt(nd[0]); int d = Integer.parseInt(nd[1]); int narr[] = new int[n]; int min = Integer.MAX_VALUE; for(int i = 0; i < n; i++){ int a = Integer.parseInt(br.readLine()); if(a < min){ min = a; } narr[i] = a; } quickSort(narr,0,n-1); for(int i = 0; i < d; i++){ int a = Integer.parseInt(br.readLine()); if(a <= min * 2){ System.out.println(0); }else{ int start = 0; int end = n -1; int max = 0; while(start < end){ int sum = narr[start] + narr[end]; if(sum <= a && sum > max) max = sum; if(sum == a){ break; } if(sum > a){ end--; }else{ start++; } } System.out.println(max); } } } catch (Exception e) { e.printStackTrace(); System.err.println("Error:" + e.getMessage()); } } }
結果を見ると無事case3まで実行完了できているようでした。
Test case 1 通過 実行時間:0.08 秒
Test case 2 通過 実行時間:0.09 秒
Test case 3 通過 実行時間:0.22 秒
と、クリアしてしまったので、ここで満足しちゃいましたが、この先更に速度を挙げためのアイデアがいくつか考えられます。
1. 探索をbinary searchにする
2. 探索時に一度探索したデータをキャッシュ化して覚えておく。ただしキャンペーン日数が75しかないので、今回のデータセットではあまり効果が薄いかもしれません。
参考文献
1. 「クイックソートのサンプルコード」
http://homepage3.nifty.com/teranet/JavaAlgorithm/QuickSort.html