Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

ゲームの攻略

あなたは所属するプログラミング部の部室から古びたボードゲームを発見しました。面白そうなので遊んでみることにしました。

このゲームは M 個のイベントから成り、時刻 ti にイベント i を攻略しなければいけません。ただし、そのときにあなたの強さは si 以上である必要があり、si 以上にできない場合はゲームオーバーになります。ゲーム開始時（時刻０）のあなたの強さは０ですが、アイテムを買うことで強さを増加させることができます。ゲーム開始時のあなたの所持金は０ですが、１単位時間あたり１増加します。

ボードにはそれぞれ１から N の番号が付けられた N 個のアイテムが順番に並べられており、アイテム i の値段は vi で、それを購入するとあなたの強さが hi 増加します。アイテムは所持金が十分であれば好きな時刻に好きな数だけ購入することができますが、残っているアイテムの中で番号が小さいものから順に選ばなければなりません。各アイテムは１度購入すると消滅します。

また、同じ時刻に複数のアイテムを連続で買うことができ、このとき隣り合うアイテムの hi の差分の和をボーナスとして得ることができます。例えば、ある時刻にアイテム１,２,３を同時に買った場合、h1 + h2 + h3 に加えて|h1 - h2| + |h2 - h3| だけあなたの強さが増加します。

あなたは、全てのイベントを攻略した後の所持金を最大化したいと考えています。

アイテムの情報とイベントの情報を入力とし、すべてのイベントを攻略した後の所持金の最大値を出力するプログラムを作成せよ。

Input

入力は以下の形式で与えられる。

N M
v1 h1
v2 h2
:
vN hN
t1 s1
t2 s2
:
tM sM

１行目にアイテムの数 N (1 ≤ N ≤ 3000) とイベントの数 M (1 ≤ M ≤ 1000) が与えられる。続く N 行にアイテム i の値段 vi と強さの増加量 hi (1 ≤ vi, hi ≤ 100000) が与えられる。続く M 行にイベント i の時刻 ti と条件 si (1 ≤ ti, si ≤ 100000) が与えられる。ただし、i < j のとき、ti < tj とする。入力はすべて整数で与えられる。

Output

所持金の最大値を１行に出力する。ただし、攻略することができない場合には「-1」を出力する。

Sample Input 1

5 4
3 3
2 1
1 5
4 2
2 6
4 1
8 2
10 4
12 17

Sample Output 1

2

Sample Input 2

5 4
3 3
2 1
1 5
4 2
2 6
4 1
8 2
10 4
12 30

Sample Output 2

-1

Solution in C++11 (judge verdict: Accepted)

#include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define all(c) (c).begin(),(c).end()
#define pb push_back
#define dbg(...) do{cerr<<__LINE__<<": ";dbgprint(#__VA_ARGS__, __VA_ARGS__);}while(0);

using namespace std;

namespace std{template<class S,class T>struct hash<pair<S,T>>{size_t operator()(const pair<S,T>&p)const{return ((size_t)1e9+7)*hash<S>()(p.first)+hash<T>()(p.second);}};template<class T>struct hash<vector<T>>{size_t operator()(const vector<T> &v)const{size_t h=0;for(auto i : v)h=h*((size_t)1e9+7)+hash<T>()(i)+1;return h;}};}
template<class T>ostream& operator<<(ostream &os, const vector<T> &v){os<<"[ ";rep(i,v.size())os<<v[i]<<(i==v.size()-1?" ]":", ");return os;}template<class T>ostream& operator<<(ostream &os,const set<T> &v){os<<"{ "; for(const auto &i:v)os<<i<<", ";return os<<"}";}
template<class T,class U>ostream& operator<<(ostream &os,const map<T,U> &v){os<<"{";for(const auto &i:v)os<<" "<<i.first<<": "<<i.second<<",";return os<<"}";}template<class T,class U>ostream& operator<<(ostream &os,const pair<T,U> &p){return os<<"("<<p.first<<", "<<p.second<<")";}
void dbgprint(const string &fmt){cerr<<endl;}template<class H,class... T>void dbgprint(const string &fmt,const H &h,const T&... r){cerr<<fmt.substr(0,fmt.find(","))<<"= "<<h<<" ";dbgprint(fmt.substr(fmt.find(",")+1),r...);}
typedef long long ll;typedef vector<int> vi;typedef pair<int,int> pi;const int inf = (int)1e9;const double INF = 1e12, EPS = 1e-9;

int main(){
	cin.tie(0); cin.sync_with_stdio(0);
	int n, m; cin >> n >> m;
	vi v(n + 1), h(n + 1);
	vi t(m), s(m);
	rep(i, n) cin >> v[i + 1] >> h[i + 1];
	rep(i, m) cin >> t[i] >> s[i];
	
	vi dh(n);
	rep(i, n - 1) dh[i + 1] = dh[i] + abs(h[i + 2] - h[i + 1]);
	rep(i, n) v[i + 1] += v[i];
	rep(i, n) h[i + 1] += h[i];
	
	vector<vi> dp(m + 1, vi(n + 1, -1));
	vector<vi> cost(n + 1, vi(n + 1, -inf));
	
	rep(i, n + 1) for(int j = i; j <= n; j++){
		int x = h[j] - h[i];
		if(i < j) x += dh[j - 1] - dh[i];
		cost[i][j] = x;
	}
	
	vi L(m + 1), R(m + 1, -1);
	R[0] = 0;
	dp[0][0] = 0;
	
	rep(i, m){
		int nL = n + 1, nR = -1;
		dp[i + 1] = dp[i];
		
		for(int j = L[i]; j <= R[i]; j++){
			
			int l = j - 1, r = n, mid;
			if(dp[i][j] + cost[j][n] < s[i]) continue;
			while(l + 1 < r){
				mid = (l + r) / 2;
				if(dp[i][j] + cost[j][mid] < s[i]) l = mid;
				else r = mid;
			}
			nL = min(nL, r);
			nR = max(nR, r);
			
			if(i && dp[i - 1][j] == dp[i][j] && L[i - 1] <= j && j <= R[i - 1])
				r = R[i] + 1;
			
			for(int k = r; k <= n && v[k] <= t[i]; k++){
				int str = dp[i][j] + cost[j][k];
				nR = max(nR, k);
				dp[i + 1][k] = max(dp[i + 1][k], str);
			}
		}
		L[i + 1] = nL; R[i + 1] = nR;
	}
	//rep(i, m + 1) dbg(i, dp[i]);
	
	int ans = -1;
	for(int i = L[m]; i <= R[m]; i++) if(dp[m][i] >= 0){
		ans = i;
		break;
	}
	if(ans < 0) cout << -1 << endl;
	else cout << t[m - 1] - v[ans] << endl;
	return 0;
}