Gym 101775B - Scapegoat - [贪心+优先队列]

题目连接:http://codeforces.com/gym/101775/problem/Bc++

Aori is very careless so she is always making troubles. One day she does it again, with N big troubles! But this time she seems to be at ease because she has found M Inklings to take all the blames. Each trouble can be measured by a severity number ai. Each trouble needs at least one Inkling to take the blame, and each Inkling can help Aori to take the blame for exactly one trouble. If two or more Inklings take the same trouble, they will take this blame together and discuss how to divide this trouble into.. some trivial things.. to reduce the pressure on each Inkling, as long as the total severity on Inklings is equal to the severity of this trouble.less

Inklings are so warm so that Aori wants to think a way to let the variance of severity on each Inkling to be minimal. Could you help Aori make her scapegoats?ide

Formally, the variance of variables is the expectation of the squared deviation of a variable from its mean:this


Input
The first line of the input gives the number of test cases, T. T test cases follow.spa

For each test case, the first line contains two integers N and M, where N is the number of troubles, and M is the number of Inklings. The next line contains N integers a1, a2, ..., aN representing the severity of the troubles that Aori makes.rest

1 ≤ T ≤ 100.
1 ≤ N ≤ M ≤ 2 × 10^5.
1 ≤ ai ≤ 10000.
.code

Output
For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the minimal variance.orm

y will be considered correct if it is within an absolute or relative error of 10 - 8 of the correct answer.blog

Example
Input
3
3 6
1 2 3
5 10
5 6 7 8 9
6 6
1 1 4 5 1 4
Output
Case #1: 0.000000000000
Case #2: 0.400000000000
Case #3: 2.888888888889three

Note
For the first sample, Aori can let one Inkling to take the first trouble's blame, two Inklings for the second, and three Inklings for the third. The severity on each Inkling is 1 unit, so their variance should be 0.

 

题意:

如今某人闯祸了,产生了 $N$ 个锅,每一个锅有个严重点数,如今能够安排 $M$ 个替罪羊去背锅。

每一个替罪羊最多只能背一个锅。若一只羊背一个锅,则该锅的严重点数所有算在它头上;若多只羊背同一个锅,则每一个羊分到该锅的一部分的严重点数。

如今考虑一种安排方案,使得全部的身上的严重点数的方差最小。

 

题解:

先考虑上 $N$ 只羊一一对应地背 $N$ 个锅,剩下 $M-N$ 个替罪羊身上严重点数均为 $0$,固然这样并非最优解。

应当把再剩下 $M-N$ 个替罪羊安排进 $N$ 个锅里分摊责任,使得方差减少。考虑贪心的思路,每次安排进去一只羊,都要使得方差减少最多。

考虑将新来的羊安排到某个任务,该任务严重点数为 $a[i]$,且原来的背锅羊数是 $num$,那么首先每一个替罪羊分到的严重点数的平均数确定是不变的 $\overline{X} = \frac{a[1]+ a[2]+ \cdots + a[n]}{m}$,所以它本来对方差的贡献为 $\frac{1}{m} \cdot num \cdot (\frac{a[i]}{num}-\overline{X})^2$。

而如今新加进去一个替罪羊,这个任务对方差的新的贡献为 $\frac{1}{m} \cdot (num+1) \cdot (\frac{a[i]}{num+1}-\overline{X})^2$。

显然,关键的差值就是 $\Delta = num \cdot (\frac{a[i]}{num}-\overline{X})^2 -(num+1) \cdot (\frac{a[i]}{num+1}-\overline{X})^2 = \frac{a[i]^2}{num \cdot (num+1)} - \overline{X}^2$,所以咱们让每次挑一个任务让它的 $\Delta + \overline{X}^2 = \frac{a[i]^2}{num \cdot (num+1)}$ 最大就行了,这个能够用优先队列。

 

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int eps=1e-10;
int n,m;
int a[maxn];
struct Node{
    int id;
    int num;
    Node(int _id,int _num) {
        id=_id, num=_num;
    }
    inline double calc()const {
        return a[id]*a[id]*1.0/num/(num+1);
    }
    bool operator<(const Node& oth)const {
        return this->calc() < oth.calc()+eps;
    }
};
priority_queue<Node> Q;
int main()
{
    int T;
    cin>>T;
    for(int kase=1;kase<=T;kase++)
    {
        scanf("%d%d",&n,&m);
        double aver=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            aver+=a[i];
            Q.push(Node(i,1));
        }
        aver/=m;
        for(int rest=m-n;rest>0;rest--)
        {
            Node now=Q.top(); Q.pop();
            Q.push(Node(now.id,now.num+1));
        }
        double ans=0;
        while(!Q.empty())
        {
            Node now=Q.top(); Q.pop();
            ans+=now.num*pow(a[now.id]*1.0/now.num-aver,2.0);
        }
        ans/=m;
        printf("Case #%d: %.9lf\n",kase,ans);
    }
}
相关文章
相关标签/搜索