ARC128 C - Max Dot(贪心+构造)

目录

Description

有一个数组 \(a\), 要求构造一个数组 \(x\),满足 \(\sum{a_i*x_i}\) 最大

其中 \(x_i\) 的大小不超过 \(m\),而且 \(\sum{x_i}=S\)\(0<=x_1<=x_2<=....x_n<=m\)

State

\(1<=n<=5000\)

\(1<=m<=10^6\)

\(1<=S<=10^6\)

\(1<=a_i<=10^6\)

Input

3 2 3
1 2 3

Output

8.00000000000000000000

Solution

先考虑一种极端的情况, \(a\) 数组为降序,此时 \(x\) 数组每个数为 \(\frac{S}{n}\)

这是题目才有下手点,我们可以从后向前找 \(\frac{sum_i}{n-i+1}\) 的最大值,如果没有 \(m\) 的限制,\(x=\frac{S}{n-i+1}\) ,此时可以贪心验证一下正确性

如果 \(x>m\) 就令这一段的 \(x\)\(m\),然后重复上述过程,直至 \(S=0\)


Code

const int N = 5e3 + 5;
 
    int n, m, k, _;
    int a[N];
    double ans[N];

signed main()
{
    // IOS;
    double m, s;
    while(~ sd(n)){
        sf(m), sf(s);
        rep(i, 1, n) sd(a[i]);
        int st = n;
        while(st > 0){
            double sum = 0;
            int pos;
            double maxx = 0;
            for(int i = st; i; i --){
                sum += a[i];
                if(sum / (st - i + 1) > maxx){
                    maxx = sum / (st - i + 1);
                    pos = i;
                }
            }
            double now = min(m, s / (st - pos + 1));
            for(int i = st; i >= pos; i --){
                ans[i] = now;
                s -= now;
            }
            if(s <= 0) break;
            st = pos - 1;
        }
        double sum = 0;
        for(int i = 1; i <= n; i ++){
            sum += a[i] * ans[i];
        }
        pf(sum);
    }
    // PAUSE;
    return 0;
}
posted @ 2021-11-01 16:09  Bcoi  阅读(104)  评论(0)    收藏  举报