• HackerRank and MiniMax


    传送门

    Sherlock and MiniMax

    Authored by darkshadows on May 07 2014


    Watson gives Sherlock an array $A_1,A_2cdots A_N$. 
    He asks him to find an integer $M$ between $P$ and $Q$ (both inclusive), such that,$min {|A_i-M|, 1le ile 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(Nlog{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
    ", 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)$为真

  • 相关阅读:
    解决shiro多次从redis读取session的问题
    软件测试其他方法
    异常HTTP Status 500
    支付
    java面试
    SQL入门
    软件测试理论基础
    软件测试学习第一章
    Linux在终端命令行模式下智能补全功能以及组合键
    Linux安装
  • 原文地址:https://www.cnblogs.com/Patt/p/4746329.html
Copyright © 2020-2023  润新知