Problem:
Problem E: Rabbit Plays Games!

うさぎがとあるロールプレイングゲームで遊んでいる. 城に入る直前で, 敵に待ち伏せされていた！

うさぎが操作する主人公1 人と, n 体の敵との戦闘となった. 各キャラクターには4 つの能力値, 体力hi, 攻撃力ai, 防御力di, 敏捷si が定められている. i = 0 は主人公の情報, 1 ≤ i ≤ n は各敵の情報を表す.

戦闘はターン制である. 各ターン, 生き残っているキャラクターが, 敏捷の値が高い順に攻撃を行う. 敵は必ず主人公を攻撃する. 主人公は敵1 体を攻撃するが, どの敵を攻撃するかは毎ターンごとに主人公が選べる.攻撃力a のキャラクターが防御力d のキャラクターに攻撃するとき, max{a − d, 0} のダメージが与えられる. 受けたダメージの合計が体力の値以上になったキャラクターは直ちに戦闘不能になってしまう. 主人公が戦闘不能になったとき, あるいは敵がすべて戦闘不能になったとき, 戦闘は終了する.

Input

1 ≤ n ≤ 40 000

1 ≤ hi, ai, di, si ≤ 1 000 000 000 (整数)

si はすべて異なる.

Output

主人公が必ず戦闘不能になってしまうとき, −1 を出力せよ. そうでないとき, 主人公が受けるダメージの合計の最小値を一行に出力せよ.

Sample Input 1

2
10 3 1 2
2 4 1 3
2 2 1 1

Sample Output 1

4

Sample Input 2

1
1 1 1 1
10000 10000 10000 10000

Sample Output 2

-1

Solution in JAVA (judge verdict: Wrong Answer)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Main {
	
	public static class Monstar implements Comparable<Monstar>{
		long atk, times;

		public Monstar(long atk, long times) {
			super();
			this.atk = atk;
			this.times = times;
		}

		@Override
		public int compareTo(Monstar o) {
			long this_mul = atk * times;
			long o_mul = o.atk * o.times;
			
			if(this_mul < o_mul){
				return 1;
			}else if(this_mul > o_mul){
				return -1;
			}else if(this.atk > o.atk){
				return -1;
			}else if(this.atk < o.atk){
				return 1;
			}else{
				return 0;
			}
		}

		@Override
		public String toString() {
			return "Monstar [atk=" + atk + ", times=" + times + "]";
		}
	}
	
	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		
		final int n = sc.nextInt();
		
		final int hp  = sc.nextInt();
		final int atk = sc.nextInt();
		final int dif = sc.nextInt();
		final int spd = sc.nextInt();
		
		long cur_hp = hp;
		Monstar[] monstars = new Monstar[n];
		
		boolean end = false;
		for(int i = 0; i < n; i++){
			final int h = sc.nextInt();
			final int a = sc.nextInt();
			final int d = sc.nextInt();
			final int s = sc.nextInt();
			
			final int ene_atk = Math.max(a - dif, 0);
			if(spd < s){
				cur_hp -= ene_atk;
			}
			
			final int own_atk = Math.max(atk - d, 0);
			if(own_atk <= 0){
				end = true;
			}else{
				int times = h / own_atk;
				if(h % own_atk != 0){
					times++;
				}
				
				
				monstars[i] = new Monstar(ene_atk, times);
			}
		}
		
		//System.out.println(Arrays.toString(monstars));
		
		if(end){
			System.out.println(-1);
			return;
		}
		
		Arrays.sort(monstars);
		int time = 0;
		for(int i = 0; i < n; i++){
			time += monstars[i].times;
			
			cur_hp -= monstars[i].atk * (time - 1);
		}
		
		if(cur_hp < 0){
			System.out.println(-1);
		}else{
			System.out.println(hp - cur_hp);
		}
	}
	
public static class Scanner {
		private BufferedReader br;
		private StringTokenizer tok;
		
		public Scanner(InputStream is) throws IOException{
			br = new BufferedReader(new InputStreamReader(is));
			getLine();
		}
		
		private void getLine() throws IOException{
			while(tok == null || !tok.hasMoreTokens()){
				tok = new StringTokenizer(br.readLine());
			}
		}
		
		private boolean hasNext(){
			return tok.hasMoreTokens();
		}
		
		public String next() throws IOException{
			if(hasNext()){
				return tok.nextToken();
			}else{
				getLine();
				return tok.nextToken();
			}
		}
		
		public int nextInt() throws IOException{
			if(hasNext()){
				return Integer.parseInt(tok.nextToken());
			}else{
				getLine();
				return Integer.parseInt(tok.nextToken());
			}
		}
		
		public long nextLong() throws IOException{
			if(hasNext()){
				return Long.parseLong(tok.nextToken());
			}else{
				getLine();
				return Long.parseLong(tok.nextToken());
			}
		}
		
		public double nextDouble() throws IOException{
			if(hasNext()){
				return Double.parseDouble(tok.nextToken());
			}else{
				getLine();
				return Double.parseDouble(tok.nextToken());
			}
		}
	}

}