HackerRank and MiniMax

传送门

Sherlock and MiniMax

Authored by darkshadows on May 07 2014


Watson gives Sherlock an array $A_1,A_2\cdots A_N$. 
He asks him to find an integer $M$ between $P$ and $Q$ (both inclusive), such that,$\min \{|A_i-M|, 1\le i\le N\}$ is maximised. If there are multiple solutions, print the smallest one.

Input Format 
The first line contains $N$. The next line contains space separated $N$ integers, and denote the array $A$. The third line contains two space separated integers denoting $P$ and $Q$.

Output Format 
In one line, print the required answer.

Constraints 
$1 \le N \le 10^2$
$1 \le A_i \le 10^9$
$1 \le P \le Q \le 10^9$

Sample Input

3
5 8 14
4 9

Sample Output

4

Explanation 
For $M$ = 4,6,7, or 9, the result is 1. Since we have to output the smallest of the multiple solutions, we print 4.

 


Solution

二分答案+$O(N)$构造

复杂度$O(N\log{Q})$

 


Implementation

 

#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define pb push_back
int n, p, q;
typedef pair<int,int> P;
vector<P> interv[2];
vector<int> a;
int now, pre;
void merge(P &a, P &b){
	int x=max(a.X, b.X);
	int y=min(a.Y, b.Y);
	if(x<=y) interv[pre].pb({x, y});
}
const int INF=INT_MAX;
bool C(int x){
	pre=0, now=1;
	interv[pre].clear();
	interv[now].clear();
	interv[now].pb({p, q});
	P l, r;
	for(int i=0; i<a.size(); i++){
		for(int j=0; j<interv[now].size(); j++){
	
			l={-INF, a[i]-x};
			r={x+a[i], INF};
			merge(interv[now][j], l);
			merge(interv[now][j], r);
		}
		if(interv[pre].empty()) return false;
		interv[now].clear();
		swap(pre, now);
	}
	return true;
}
int bs(int l, int r){ //max
	int mid;
	while(r-l>1){
		mid=(l+r)>>1;
		if(C(mid)) l=mid;
		else r=mid;
	}
	return l;
}
int main(){
	//freopen("in", "r", stdin);
	scanf("%d", &n);
	for(int i=0; i<n; i++){
		int b;
		scanf("%d", &b);
		a.push_back(b);
	}
	sort(a.begin(), a.end());
	a.erase(unique(a.begin(), a.end()), a.end());
	scanf("%d%d", &p, &q);
	C(bs(0, 1e9));
	sort(interv[now].begin(), interv[now].end());
	printf("%d\n", interv[now][0].X);
}

总结

二分答案类问题

提法

求满足条件$C(x)$的最大/最小的$x$,其中$C(x)$是一个关于$x$的bool表达式。

这类问题能用二分答案解决的条件是$C(x)$要有单调性,这具体是指

若求使$C(x)$为真的最大的$x$,那么$C(x)$必须满足

若$C(x_0)$为真,则 $\forall x \le x_0, C(x)$为真

若求使$C(x)$为真的最小的$x$,那么$C(x)$必须满足

若$C(x_0)$为真,则 $\forall x \ge x_0,C(x)$为真

posted @ 2015-08-20 21:33  Pat  阅读(374)  评论(0编辑  收藏  举报