• 【洛谷5308】[COCI2019] Quiz(WQS二分+斜率优化DP)


    点此看题面

    大致题意: 你要把(n)划分恰好(k)个非空段,设第(i)段长为(a_i),求(sum_{i=1}^kfrac{a_i}{sum_{j=1}^ia_j})的最大值。

    (WQS)二分

    考虑到恰好(k)段这个限制,显然划分为更多的段数必然能够得到更优的答案,因此可以(WQS)二分。

    具体地,二分选择一段的额外代价(C),只要在每次选取新一段时给答案减去(C)即可。

    斜率优化(DP)

    考虑我们设(f_i)表示划分出(1sim i)所能得到的最大收益,暴力想法就是枚举一个(j),得到:

    [f_i=f_j+frac {i-j}i-C=f_j-frac ji+1-C ]

    其中(1-C)明显是常数项,因此对于两个转移点(x,y)(x>y)),(x)的答案优于(y)的答案需要满足:

    [f_x-frac xi>f_y-frac yi ]

    [frac{x-y}i<f_x-f_y ]

    [i>frac {x-y}{f_x-f_y} ]

    因此我们只要开一个单调队列,维护斜率单调递增,每次弹出不再有贡献的队首,再从队首转移即可。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define DB long double
    #define eps 1e-12
    using namespace std;
    int n,k,q[N+5],g[N+5];DB f[N+5];//f记录最大收益,g记录划分段数
    I int Check(Con DB& C)//斜率优化DP,C为当前额外代价
    {
    	RI i,H=1,T=0;for(q[++T]=0,i=1;i<=n;++i)//初始放入0
    	{
    		W(H<T&&i*(f[q[H+1]]-f[q[H]])>q[H+1]-q[H]) ++H;f[i]=f[q[H]]-1.0*q[H]/i+1-C,g[i]=g[q[H]]+1;//弹出不优队首,然后从队首转移
    		W(H<T&&(q[T]-q[T-1])*(f[i]-f[q[T]])>(i-q[T])*(f[q[T]]-f[q[T-1]])) --T;q[++T]=i;//在队尾加入当前点,维护斜率递增
    	}return g[n];//返回在当前额外代价下的最大收益
    }
    int main()
    {
    	scanf("%d%d",&n,&k);DB l=0,r=1e9,mid;
    	W(r-l>eps) Check(mid=(l+r)/2)<=k?r=mid:l=mid;//WQS二分
    	return Check(r),printf("%.9Lf",f[n]+k*r),0;//最终答案
    }
    
  • 相关阅读:
    MFC学习笔记2添加资源
    汇编语言基础教程数据类型
    MFC学习笔记3引用资源
    asp.net MVC留言本示例
    汇编语言学习笔记按指定的字体输出文本
    C#(winform)项目中自制alert提示窗体并引用系统图标资源
    报表打印(rdlc)
    在内存中序列化,反序列化对象实体 来完成对象实体的深拷贝
    Hibernate中ORA01502错误的解 ...
    NHibernate的调试技巧和Log4Net配置
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu5308.html
Copyright © 2020-2023  润新知