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: Accepted)

import java.awt.List;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.TreeSet;
 
public class Main {
	
	public static class Monster implements Comparable<Monster>{
		long atk;
		long live;
		
		private Monster(long atk, long live) {
			super();
			this.atk = atk;
			this.live = live;
		}

		@Override
		public int compareTo(Monster arg0) {
			long own = this.atk * arg0.live;
			long oth = arg0.atk * this.live;
			
			if(own < oth){
				return 1;
			}else if(own > oth){
				return -1;
			}else{
				return 0;
			}
		}
	}
	
	public static void main(String[] args) throws IOException{
		Scanner sc = new Scanner(System.in);
		
		final int n = sc.nextInt();
		
		final long hp = sc.nextLong();
		final long atk = sc.nextLong();
		final long def = sc.nextLong();
		final long spd = sc.nextLong();
		
		ArrayList<Monster> monsters = new ArrayList<Main.Monster>();
		
		boolean tumi = false;
		long current_hp = hp;
		for(int i = 0; i < n; i++){
			final long h = sc.nextLong();
			final long a = sc.nextLong();
			final long d = sc.nextLong();
			final long s = sc.nextLong();
			
			final long monster_atk = Math.max(a - def, 0);
			final long usagi_atk = Math.max(atk - d, 0);
			
			if(spd < s){
				current_hp -= monster_atk;
			}
			
			if(usagi_atk == 0 && !(monster_atk == 0)){
				tumi = true;
				continue;
			}else if(monster_atk == 0){
				continue;
			}
			
			long live = h / usagi_atk;
			if(h % usagi_atk != 0){
				live++;
			}
			
			monsters.add(new Monster(monster_atk, live));
		}
		
		if(tumi || current_hp <= 0){
			System.out.println(-1);
			return;
		}
		
		Collections.sort(monsters);
		
		long turn = 0;
		for(Monster monster : monsters){
			turn += monster.live;
			
			current_hp -= (turn - 1) * (monster.atk);
			if(current_hp <= 0){
				break;
			}
		}
		
		System.out.println((current_hp <= 0) ? -1 : (hp - current_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());
			}
		}
	}
}