zoukankan      html  css  js  c++  java
  • hdu 4923 Room and Moor (单调栈+思维)

    题意:

    给一个0和1组成的序列a,要构造一个相同长度的序列b。b要满足非严格单调,且

    值为0到1的实数。最后使得  sum((ai-bi)^2)最小。


    算法:

    首先a序列開始的连续0和末尾的连续1是能够不考虑的。

    由于仅仅要b序列相应开头为0、

    末尾为1,既不影响单调性又能使相应的(ai-bi)^2=0。

    然后,

    先找111100、11100、10这样以1開始以0结束的序列块。每一块相应的b值相等且均为

    这一块的平均值,即1的个数/0和1的总个数。

    可是要满足b的单调性,则我们用栈来维护,假设后面一块的均值<前面一块的均值,则

    合并这两块。也就是仅仅要栈顶的块的均值小于要压入栈的块的均值,就一直合并,直到

    满足单调性。再把当前的值压入栈。

    最后仅仅要一块块统计相应的sum((ai-bi)^2)就是答案了。


    逗逼记忆---->比赛的时候我没有想到块,仅仅想到除去前面的0和后面的1。中间的值都是一样。

    用二分或者三分解决,仅仅要控制精度=。

    =


    P.S:   这题必须注意细节,否则极易丢失精度。主要是我代码凝视的两个我開始没有控制好的地方。

    o(╯□╰)o


    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define maxn 100010
    using namespace std;
    
    struct node
    {
        double num,v; //v表示1的个数,num表示0和1的总个数
    };
    node stk[maxn];
    double sum[maxn],a[maxn];
    
    int main()
    {
        int T,n;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            memset(sum,0,sizeof(sum));
            for(int i=1;i<=n;i++)
            {
                scanf("%lf",&a[i]);
                sum[i] = sum[i-1]+a[i];
            }
            int i = 1,k = n;
            while(a[i]==0) i++;
            while(a[k]==1) k--;
            int top = 0,le = i;
            node x,y;
            for(;i<=k;i++)
            {
                if(a[i]==0)
                {
                    while(a[i]==0 && i<=k) //这里假设不加控制i<=k,i可能超出k
                        i++;
                    double a = sum[i-1]-sum[le-1];
                    double b = (double)i-le;
                    while(top>0 && a/b<stk[top].v/stk[top].num) //这里也不能忘了top>0
                    {
                        y = stk[top--];
                        a += y.v;
                        b += y.num;
                    }
                    x.v = a;
                    x.num = b;
                    stk[++top] = x;
                    le = i;
                }
            }
            double ans = 0;
            while(top)
            {
                y = stk[top--];
                double val = y.v/y.num;
                ans += (1-val)*(1-val)*y.v + val*val*(y.num-y.v);
            }
            printf("%.6lf
    ",ans);
        }
        return 0;
    }
    






  • 相关阅读:
    游戏程序设计DirectX 9
    面试题1
    [python爬虫] Selenium定向爬取PubMed生物医学摘要信息
    Python简单实现基于VSM的余弦相似度计算
    [python爬虫] Selenium常见元素定位方法和操作的学习介绍
    [python爬虫] 爬取图片无法打开或已损坏的简单探讨
    [python] 安装numpy+scipy+matlotlib+scikitlearn及问题解决
    [python] 使用Jieba工具中文分词及文本聚类概念
    javascript在firefox中对Dom的处理的一个问题
    XML和DOM节点的NodeType
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5240246.html
Copyright © 2011-2022 走看看