分析

听同学说调了很久,主页也看到好几个帖子,就来看了看,受二分误导调了很久,但显然正确性有问题,考虑对同一组数据 \(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;
}
posted on 2021-11-19 11:33  漠寒·  阅读(69)  评论(0编辑  收藏  举报