Codeforces 1301B Motarack's Birthday(二分)

题目链接:http://codeforces.com/problemset/problem/1301/B

思路:

(1)都是-1的情况

(2)只有一个除-1之外的数

(3)至少有两个除-1之外的不同的数字

对于(3),我们可以得出最大数字和最小数字_max,_min,而我们的答案m和k易得一定是在[_max,_min]中得出,

那么我们当然可以初始化m = (_max-_min)。因为数据范围大,我们可以通过二分来处理这个答案。

我们可以二分mid ∈[L=_min,R=_max],枚举k,然后把k带入原数组,覆盖-1,在这个k的情况下,tmp_m最大是多少,

并且记录tmp_m最大的时候,两个坐标,dx,dy。为什么要记录两个坐标呢,因为我们不知道怎么二分才是最优的,

而我们可以想到,在一个一维坐标上,(x-----------mid--------y),“--"表示距离,dis(max(mid-x,y-mid)) = m,我们想的是

可不可以让m变小,那么我们可以让这个距离尽可能的平分,那么m就最小了。

显然:如果tmp_m<m那么更新m = tmp_m,k = mid。

这里有一种特殊情况(  -1 -1 -1 40 35 -1 35 ),m = (_max-_min)就是答案,所以一开始对k也要初始化一下,显然k = _max or _min都可。

 1 #include <iostream>
 2 #include <string>
 3 #include <cstdio>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 
 8 const int N = (int)2e5+100,inf = (int)1e9+100;
 9 int a[N];
10 int m,k,l,r,n,mid;
11 
12 void fun(int mid){
13     int dx,dy,inx_x,inx_y,tmp_m = -1;
14     for(int i = 1; i < n; ++i){
15         if(a[i-1] == -1 && a[i] == -1) continue;
16         dy = a[i] == -1? mid : a[i];
17         dx = a[i-1] == -1? mid : a[i-1];
18         if(abs(dx-dy) > tmp_m){//tmp_m最大化
19             tmp_m = abs(dx-dy);
20             inx_x = i-1; inx_y = i;//坐标
21         }
22     }
23     int v = a[inx_x] == -1 ? a[inx_y] : a[inx_x];
24     if(v >= mid) l = mid + 1;// x-------mid-----------v
25     else r = mid - 1;       //  v-----------mid------x
26 
27     if(tmp_m < m){//m最小化
28         m = tmp_m; k = mid;
29     }
30 }
31 
32 int main(){
33 
34     ios::sync_with_stdio(false);
35     cin.tie(0); cout.tie(0);
36 
37     int T;
38     cin >> T;
39     while(T--){
40         cin >> n;
41         int _min = inf,_max = -1;
42         for(int i = 0; i < n; ++i){
43             cin >> a[i];
44             if(a[i] == -1) continue;
45             _min = min(_min,a[i]);
46             _max = max(_max,a[i]);
47         }
48 
49         if(_min == inf && _max == -1) cout << 0 << " " << 0 << endl;
50         else if(_max == _min) cout << 0 << " " << _min << endl;
51         else{
52             l = _min,r = _max,mid,k = _min;
53             m = r-l;
54             while(l <= r){
55                 mid = (l+r)>>1;
56                 fun(mid);
57             }
58             cout << m << " " << k << endl;
59         }
60     }
61 
62     return 0;
63 }
原文地址:https://www.cnblogs.com/SSummerZzz/p/12345854.html