刚开始直接硬来,要么TLE要么WA
后面改成另一种思路:
先把ai大于n的全都转换为刚好小于n的数,记录在cnt[i]中,代表ai有多少个
然后从高往低走,把cnt大于1的分到下面去,使数尽可能分布得广一些
然后从低往高开始算,如果该数存在,则换下一个数,否则从高处请求数往下降
代码如下:
#include<cstdio>
#include<cstring>
const int maxn = 100010;
int cnt[maxn], n;
int main(void){
int T; scanf("%d", &T);
while(T--){
scanf("%d", &n); memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < n; i++){
int val; scanf("%d", &val);
while(val > n) val >>= 1;
cnt[val]++;
}
for(int i = n; i; i--){
if(!cnt[i]) continue;
cnt[i >> 1] += cnt[i] - 1;
cnt[i] = 1;
}
for(int i = 0; i < n; i++){
if(cnt[i]) continue;
while(i < n){
int x = n;
while(x && cnt[x]) x >>= 1;
cnt[x] += cnt[n];
if(cnt[i]) break;
n--;
}
}
printf("%d\n", n);
}
return 0;
}