zoukankan      html  css  js  c++  java
  • CF1299C Water Balance

    Solution

    要求字典序最小,那么前面的值要尽量小,那就不妨先考虑前面的值。两段有交部分的操作是很难处理的,肯定需要某种转换。所以想到观察两段有交的操作会产生什么样的效果。简单的分类讨论之后,会发现无论怎么操作都对前面的数没有正的贡献,反而有可能把前面的一段数变大。由于有交的操作一定不会更优,所以最后的操作一定是不相交的。那么问题就转换成了将一个序列分成若干段,满足越前面的段平均值越小越好,求最优的序列。

    用增量法,假设前面已经有一个段了,考虑要不要把当前新的数加入这个段。如果合并后平均值变小了,那么合并进去更优;反之,则新开一段。但如果合并了后平均值变小了,就可能出现比更前面一段的平均值还小的情况,显然再把这两段合并更优。如此迭代。容易想到用单调栈来维护这个过程。

    #include<stdio.h>
    #define N 1000007
    #define db double
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    struct Node{
        db sum; int num;
        db calc(){return sum/num;}
        Node operator +(const Node &X) {
            Node A;
            A.sum=sum+X.sum,A.num=num+X.num;
            return A;
        }
    }sta[N];
    
    int n,top=0;
    int main(){
        n=read();
        for(int i=1;i<=n;i++){
            Node now; now.sum=read(),now.num=1;
            while(top&&sta[top].calc()>now.calc()) 
                now=now+sta[top--];
            sta[++top]=now;
        }
        for(int i=1;i<=top;i++)
            for(int j=1;j<=sta[i].num;j++) printf("%.9lf
    ",sta[i].sum/sta[i].num);
    }
    
  • 相关阅读:
    Windows 7任务栏图标特别说明
    Linux下send函数 Broken pipe错误的解决方法
    C++实现一个简单的异常日志记录类
    C++写日志操作
    VC中设置打开文件的权限为管理员权限
    MFC 注册热键
    监控Tomcat状态及配置AIO(APR)模式
    Tomcat管理功能使用及WEB站点部署
    Tomcat多实例配置
    基于端口主机的虚拟主机
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14155797.html
Copyright © 2011-2022 走看看