题目描述
小蓝的班上有 n n n 个人,一次考试之后小蓝想统计同学们的成绩,第 i i i 名同学的成绩为 a i a_i a i 。当小蓝统计完前 x x x 名同学的成绩后,他可以从 1 ∼ x 1 \sim x 1 ∼ x 中选出任意 k k k 名同学的成绩,计算出这 k k k 个成绩的方差。小蓝至少要检查多少个人的成
绩,才有可能选出 k k k 名同学,他们的方差小于一个给定的值 T T T ?
提示:k k k 个数 v 1 , v 2 , ⋯ , v k v_1, v_2, \cdots , v_k v 1 , v 2 , ⋯ , v k 的方差 σ 2 \sigma^2 σ 2 定义为:σ 2 = ∑ i = 1 k ( v i − v ˉ ) 2 k \sigma^2=\dfrac {\sum_{i=1}^k(v_i-\bar v)^2} k σ 2 = k ∑ i = 1 k ( v i − v ˉ ) 2 ,其中 v ˉ \bar v v ˉ 表示
v i v_i v i 的平均值,v ˉ = ∑ i = 1 k v i k \bar v = \dfrac {\sum_{i=1}^k v_i} k v ˉ = k ∑ i = 1 k v i 。
输入格式
输入的第一行包含三个正整数 ,相邻整数之间使用一个空格分隔。
第二行包含 n n n 个正整数 a 1 , a 2 , ⋯ , a n a_1, a2, \cdots, a_n a 1 , a 2 , ⋯ , a n ,相邻整数之间使用一个空格分隔。
输出格式
输出一行包含一个整数表示答案。如果不能满足条件,输出 − 1 -1 − 1 。
样例 #1
样例输入 #1
样例输出 #1
提示
检查完前三名同学的成绩后,只能选出 ,方差为 ;
检查完前四名同学的成绩后,可以选出 ,方差为 ,所以答案为 。
对于 10 % 10\% 1 0 % 的评测用例,保证 1 ≤ n , k ≤ 1 0 2 1 ≤ n, k ≤ 10^2 1 ≤ n , k ≤ 1 0 2 ;
对于 30 % 30\% 3 0 % 的评测用例,保证 1 ≤ n , k ≤ 1 0 3 1 ≤ n, k ≤ 10^3 1 ≤ n , k ≤ 1 0 3 ;
对于所有评测用例,保证 , , 。
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <bits/stdc++.h> using namespace std;typedef long long LL;typedef double db;LL n,k,T,a[100005 ],s[100005 ],qsum[100005 ],qpf[100005 ]; bool check (LL x) { for (int i=1 ;i<=x;i++) s[i]=a[i]; sort (s+1 ,s+x+1 ); qsum[0 ]=0 ,qpf[0 ]=0 ; for (int i=1 ;i<=x;i++) qsum[i]=qsum[i-1 ]+s[i]; for (int i=1 ;i<=x;i++) qpf[i]=qpf[i-1 ]+s[i]*s[i]; db fc=0 ,avg=0 ; for (int i=1 ;i<=k;i++) avg+=(db)s[i]/k; fc=(qpf[k]-2 *avg*qsum[k]+k*avg*avg)/k; if (T>=fc){ return true ; } for (int i=k+1 ;i<=x;i++){ avg=avg-(db)s[i-k]/k+(db)s[i]/k; fc=(qpf[i]-qpf[i-k]-2 *avg*(qsum[i]-qsum[i-k])+k*avg*avg)/k; if (T>=fc){ return true ; } } return false ; } int main () { cin>>n>>k>>T; for (int i=1 ;i<=n;i++) cin>>a[i]; LL l=k,r=n; LL ans=n+1 ; while (l<=r){ int mid=l+(r-l)/2 ; if (check (mid)){ ans=mid; r=mid-1 ; }else { l=mid+1 ; } } if (ans>n) cout<<-1 ; else cout<<ans; return 0 ; }