hdu 4923 单调栈

http://acm.hdu.edu.cn/showproblem.php?pid=4923

给定一个序列a,元素由0,1组成,求一个序列b,元素在0~1之间,并且保证递增。输出最小的∑(ai−bi)2

对于每个由连续1开头,连续0结尾的段落有最优值x=a/a+b = sum/len (a为1的个数,b为0的个数),用栈维护各个段的x(d[i])值,如果当前x值小于前面一个段的x值,那么就要将两个段合并,相应调整sum和len.

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define clr0(x) memset(x,0,sizeof(x))

typedef long long LL;
int a[100005],s[100005],l[100005],r[100005],top;
double d[100005];
int main(){
    int n,_;
    RD(_);
    while(_--){
        top = 0;s[0] = 0;
        RD(n);
        for(int i = 1;i <= n;++i){
            RD(a[i]);s[i] = s[i-1]+a[i];
        }
        for(int i = 1;i <= n;){
            int j = i;
            d[++top] = a[i];
            while (j < n && a[j] >= a[j+1])
                d[top] += a[++j];
            l[top] = i;
            r[top] = j;
            d[top] /= (j-i+1);
            while (top > 1 && d[top] < d[top-1]){
                r[top - 1] = r[top];
                --top;
                d[top] = 1.0*(s[r[top]] - s[l[top]-1]) / (r[top]-l[top]+1);
            }
            i = j+1;
        }
        double ans = 0;
        for (int k=1;k<=top;++k)
            for (int i=l[k];i<=r[k];++i) ans += (d[k]-a[i])*(d[k]-a[i]);
        printf("%.6f\n",ans);
    }
    return 0;
}


转载于:https://www.cnblogs.com/zibaohun/p/4046770.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值