• 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);
    }
    
  • 相关阅读:
    存储过程拆分字符窜
    jquery学习
    Sql常用语法
    存储过程分页
    asp.net 定时执行程序
    C# 多线程并发处理数据库数据,发送信号等待处理完统一插入.(转)
    (转)CAS 单点登录安装笔记4
    C# 自动退出当前程序,然后再启动
    给自己的Web文件夹增加一个图片或其它文件认证
    Setting NTFS Permissions with C#
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14155797.html
Copyright © 2020-2023  润新知