C. Add, Divide and Floor
链接:https://codeforces.com/problemset/problem/1901/C
洛谷链接:https://www.luogu.com.cn/problem/CF1901C
思路:
首先去重:这里建议分清楚总操作数n和元素总数cnt。
然后把去重的元素放在数组中,sort让它升序,取两个极端的差。(因为中间的数会被并到里面去,就是说,可以理解为区间收缩)
分为两步:
①计数:2^k≤delta
的时候,k++,意味着要多少次;
②写每次的数:当k≤n时,就可以左偏取数,注意最后一个特判:当差为1的时候,即:left = right - 1
,取最后一次的为right + 1
(因为是左偏),所以完成
代码:
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
#include<set>
typedef long long ll;
using namespace std;
const int N = 2e5 + 10;
int lst[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t; cin >> t;
while (t--)
{
int n; cin >> n;
map<int, bool>mp;
int cnt=0;
int xx;
for (int i = 0; i < n; i++)
{
cin >> xx;
if (!mp[xx])
{
mp[xx] = 1;
lst[cnt] = xx;
cnt++;
}
}
if (n == 1 or cnt == 1) { cout << '0' << endl; continue; }
sort(lst, lst + cnt);
int minn = lst[0], maxn = lst[cnt - 1];
int delta = maxn - minn;
int k = 1; int kpp = 2;
while (kpp <= delta)
{
kpp <<= 1;
k++;
}
cout << k << endl;
if (k <= n)
{
while (minn + 1 < maxn)
{
int mid = minn + (maxn - minn + 1) / 2;
cout << mid;
minn = (minn + mid) / 2, maxn = (maxn + mid) / 2;
if (minn + 1 <= maxn)cout << ' ';
}
cout << maxn + 1 << endl;
}
}
return 0;
}