mayoko’s diary

プロコンとかいろいろ。

SRM 548 div1 easy: KingdomAndTrees

問題

TopCoder Statistics - Problem Statement

n 本の木が与えられ, それぞれは高さ h[i] である。レベル X の魔法を使うと, それぞれの木の高さを, [max(1, h[i]-X), h[i]+X] の範囲に変化させることが出来る(ただし高さは整数にしなければならない)。この魔法を 1 回使うことによって, 木を狭義に単調増加させたい。
魔法レベルを最小化せよ。

解法

二分探索します。

x でOK かどうか判定する関数 ok(x) = (レベル x の魔法で足りるか?)は, h[i+1] > h[i] を満たす範囲で h[i+1] を最小化させるように魔法を打っていけば良いです。

bool ok(ll x, vector<int> heights) {
	int n = heights.size();
	vector<ll> hs(n);
	for (int i = 0; i < n; i++) 
		hs[i] = heights[i];
	hs[0] = max(1ll, hs[0]-x);
	for (int i = 1; i < n; i++) {
		if (hs[i]+x <= hs[i-1]) return false;
		if (hs[i]-x > hs[i-1]) hs[i] -= x;
		else hs[i] = hs[i-1]+1;
	}
	return true;
}

class KingdomAndTrees {
public:
    int minLevel(vector <int> heights) {
        ll low = -1, high = 1ll<<55;
        while (high-low > 1) {
        	const ll med = (high+low)/2;
        	if (ok(med, heights)) high = med;
        	else low = med;
        }
        return (int)high;
    }
};