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;

}

posted on 2024-05-01 10:25  WHUStar  阅读(7)  评论(0编辑  收藏  举报