分析
听同学说调了很久,主页也看到好几个帖子,就来看了看,受二分误导调了很久,但显然正确性有问题,考虑对同一组数据 \(k\) 变化的影响。
显然,在删数时只会导致能删的更多,\(k\) 变小也会使删的更多,所以先读入所有的 \(k\),自大到小排序处理,这样答案单调递减,每个数就只用删一次就可以了。
代码
#include <bits/stdc++.h>
using namespace std;
#define N 1000010
#define int long long
inline void read(int &res){
res=0;
int f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
res*=f;
}
int T;
int a[N];
double b[N];
double avg[N];
int k[N];
int sum[N];
int ans[N];
int n, q;
struct node{
int k,id;
}c[N];
bool cmp(node aa,node bb){
return aa.k>bb.k;//结构体排序,因为要顺序输出答案
}
inline void clean(){
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(sum, 0, sizeof(sum));
memset(k, 0, sizeof(k));
memset(avg, 0, sizeof(avg));
memset(ans, 0, sizeof(ans));
return ;
}
signed main(){
read(T);
while(T--){
clean();
read(n), read(q);
for(int i = 1; i <= n; i++)
read(a[i]);
for(int i = 1; i <= q; i++)
read(c[i].k),c[i].id=i;
sort(a + 1, a + n + 1);
for(int i = 1; i <= n; i++)
b[i] = (double)a[i];
for(int i = 1; i <= n; i++)
sum[i] = sum[i - 1] + a[i];
for(int i = 1; i <= n; i++)
avg[i] = (double)(sum[n] - sum[i - 1]) / (double)(n - i + 1);
sort(c+1,c+q+1,cmp);
int pos=1;//pos即下一个考虑要删除的数
for(int i = 1; i <= q; i++){
ans[c[i].id]=0;
while(pos<=n&&b[pos]<avg[pos]-c[i].k)pos++;//要删
ans[c[i].id]=n-pos+1;
}
for(int i = 1; i <= q; i++)
printf("%lld ", ans[i]);
printf("\n");
}
return 0;
}