CF2255D-题解
题解-CF2255D
题目分析
对于某个数
设第
同理,连续做
移项有
- 有
k 个权值1,2,4,\cdots,2^{k-1} ,每个权值必须分给某一个a_i ,问能否让每个a_i 分到的权值总和至少为a_i 。
考虑对于固定的
实时最大值可以用堆,但因为实际检查次数很少 sort 轰过去也行。
操作次数下界应该是
代码实现
注意开 long long,check 函数可以利用
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define db double
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
const int N=2e5+10;
int a[N];
int b[N];
int n;
bool check(int k)
{
for(int i=1;i<=n;i++)
{
a[i]=b[i];
}
int u=n;
for(int i=k-1;i>=0 && u;i--)
{
if(i>=32 || (1ll<<i) >=a[u]) u--;
else
{
a[u]-=(1ll<<i);
sort(a+1,a+u+1);
}
}
return u==0;
}
signed main()
{
int sti=clock();
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T;
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i];
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
b[i]=a[i];
}
int l=n,r=n+32;
int ans=-1;
while(l<=r)
{
int mid=(l+r)/2;
if(check(mid))
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
cout<<ans<<endl;
}
// cerr<<1.0*(clock()-sti)/CLOCKS_PER_SEC<<endl;
return 0;
}