题目链接
http://codeforces.com/contest/722/problem/D
思路
最大值最小问题,显然二分
二分一下最大值的大小,然后每次去judge
judge的思路:设上限为y,对于一个元素x,首先缩小到
x≤y
,然后如果集合里面已经存在x了,那么
x=x/2
,直到能够插入x
细节
答案是在judge函数里面插入的,二分的时候如果judge(L) M = R,此时没有进入judge函数,于是没有输出= =
代码
#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;
#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
const int maxn = 50000 + 5;
int a[maxn], n;
set<int> res;
bool judge(int y) {
set<int> ans;
for (int i = 0; i < n; i++) {
int x = a[i];
if (x < y) ans.insert(x);
else {
bool flag = false;
while (x > y) x /= 2;
while (x) {
if (!ans.count(x)) {
ans.insert(x);
flag = true;
break;
} else {
x /= 2;
}
}
if (!flag) return false;
}
}
res.clear();
for (set<int>::iterator it = ans.begin(); it != ans.end(); it++) res.insert(*it);
return true;
}
int main() {
scan(n);
for (int i = 0; i < n; i++) scan(a[i]);
sort(a, a + n);
int L = 0, R = 1e9, M = (L + R) >> 1;
while (L < R) {
if (R == L + 1) {
if (judge(L)) M = L;
else {
judge(R);
M = R;
}
break;
} else {
M = (L + R) >> 1;
if (judge(M)) R = M;
else L = M;
}
}
for (set<int>::iterator it = res.begin(); it != res.end(); it++) printf("%d ", *it);
return 0;
}