有很多比较显然的性质。首先每个城市(除1外)至多被连通一次,否则没有意义。其次将城市按水位从大到小排序后,用以连通的城市集合是一段前缀,并且不应存在比1城市还小的。然后如果确定了选取的城市集合,每次选择也应该是连续的一段,且应从小到大选,这样保证了将其他城市的水尽量分到1,而不是被另外的城市分流。同时也说明如果不考虑次数限制应该划分的尽量多。

  考虑怎么用这些性质做。按水位从小到大排序,考虑大力dp,即设f[i][j]为前i个城市(可以不全选)分了j组时的答案,转移即f[i][j]=max{(f[k][j-1]+si-sk)/(i-k+1)}。转移显然可以看做是找该点与其他点的斜率最大值,可以在下凸壳上三分。于是可以得到一个O(nkplogn)的优秀算法。

  感觉上这个高精度的保留位数实在有点唬人,哪来那么大误差啊?于是考虑直接用long double,记录转移点,最后再用高精度计算答案。直接从复杂度里去掉了一个p,效果拔群。获得了82分的好成绩,3T1WA。又瞎猜了一发答案随分组数量变化是个凸函数,搞了个wqs二分上去,非常惨的假掉了。然后突然发现之前的82分代码算斜率甚至忘了return,加上之后获得了94分的好成绩,get了两个WA。再冷静一下发现之前因为空间不够把数组开小了,改成滚动之后又过掉最后一个点,获得了97分的好成绩。然后想起来没有把<h1的去掉因为感觉没有必要,去掉之后,就过了。

  就这么水过算了我不管了反正正解那种结论怎么猜的到啊。

//以下代码删除了高精度类
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include <string>
#include<algorithm>
using namespace std;
#define ll long long
#define N 8010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,p,a[N],b[N],from[N][N],q[N],h;
long double f[][N];
Decimal calc(int m,int n)
{
if (m==) return Decimal(h);
return (calc(m-,from[m][n])+a[n]-a[from[m][n]])/(n-from[m][n]+);
}
long double slope(int j,int x,int y){return ((a[y]-f[j][y])-(a[x]-f[j][x]))/(y-x);}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4654.in","r",stdin);
freopen("bzoj4654.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read(),p=read();
for (int i=;i<=n;i++) a[i]=read();h=a[];
int t=;for (int i=;i<=n;i++) if (a[i]>h) b[++t]=a[i];
sort(b+,b+t+);n=t;for (int i=;i<=n;i++) a[i]=b[i];
for (int i=;i<=n;i++) a[i]+=a[i-];
for (int i=;i<=n;i++) f[][i]=h;
for (int j=;j<=min(n,m);j++)
{
int tail=;memset(f[j&],,sizeof(f[j&]));
for (int i=;i<=n;i++)
{
while (tail>&&slope(j&^,q[tail-],q[tail])>slope(j&^,q[tail],i-)) tail--;
q[++tail]=i-;
int l=,r=tail;
while (l+<r)
{
int mid1=(l+r>>)-,mid2=(l+r>>)+;
if ((f[j&^][q[mid1]]+a[i]-a[q[mid1]])*(i-q[mid2]+)<(f[j&^][q[mid2]]+a[i]-a[q[mid2]])*(i-q[mid1]+)) l=mid1;else r=mid2;
}
for (int k=l;k<=r;k++)
if (f[j&^][q[k]]+a[i]-a[q[k]]>f[j&][i]*(i-q[k]+)) f[j&][i]=(f[j&^][q[k]]+a[i]-a[q[k]])/(i-q[k]+),from[j][i]=q[k];
}
}
cout<<calc(min(n,m),n).to_string(p+);
return ;
}

BZOJ4654 NOI2016国王饮水记(动态规划+三分)的更多相关文章

  1. [UOJ#223][BZOJ4654][Noi2016]国王饮水记

    [UOJ#223][BZOJ4654][Noi2016]国王饮水记 试题描述 跳蚤国有 n 个城市,伟大的跳蚤国王居住在跳蚤国首都中,即 1 号城市中.跳蚤国最大的问题就是饮水问题,由于首都中居住的跳 ...

  2. luogu P1721 [NOI2016]国王饮水记 斜率优化dp 贪心 决策单调性

    LINK:国王饮水记 看起来很不可做的样子. 但实际上还是需要先考虑贪心. 当k==1的时候 只有一次操作机会.显然可以把那些比第一个位置小的都给扔掉. 然后可以得知剩下序列中的最大值一定会被选择. ...

  3. BZOJ4654/UOJ223 [Noi2016]国王饮水记

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  4. uoj233/BZOJ4654/洛谷P1721 [Noi2016]国王饮水记 【dp + 斜率优化】

    题目链接 uoj233 题解 下面不加证明地给出几个性质: 小于\(h[1]\)的城市一定是没用的 任何城市联通包含\(1\)且只和\(1\)联通一次 联通顺序从小到大最优 单个联通比多个一起联通要优 ...

  5. [Noi2016]国王饮水记

    来自FallDream的博客,未经允许,请勿转载,谢谢. 跳蚤国有 n 个城市,伟大的跳蚤国王居住在跳蚤国首都中,即 1 号城市中.跳蚤国最大的问题就是饮水问题,由于首都中居住的跳蚤实在太多,跳蚤国王 ...

  6. P1721 [NOI2016] 国王饮水记 题解

    蒟蒻的第一篇黑题题解,求过. 题目链接 题意描述 这道题用简洁的话来说,就是: 给你 \(n\) 个数字,你可以让取其中任意若干个数字,每次操作,都会使所有取的数字变为取的数字的平均数,并且你最多只能 ...

  7. 【BZOJ4654】【NOI2016】国王饮水记(动态规划,斜率优化)

    [BZOJ4654][NOI2016]国王饮水记(动态规划,斜率优化) 题面 BZOJ 洛谷 题解 首先肯定是找性质. 明确一点,比\(h_1\)小的没有任何意义. 所以我们按照\(h\)排序,那么\ ...

  8. *UOJ#223. 【NOI2016】国王饮水记

    $n \leq 8000$的数列,问不超过$m \leq 1e9$次操作后第一个数字最大是多少.操作:选一些数,把他们变成他们的平均值.需要保留$p \leq 3000$位小数,提供了一个小数高精度库 ...

  9. [NOI 2016]国王饮水记

    Description 题库链接 给出 \(n\) 个水杯,每个水杯装有不同高度的水 \(h_i\) ,每次可以指定任意多水杯用连通器连通后断开,问不超过 \(k\) 次操作之后 \(1\) 号水杯的 ...

随机推荐

  1. C++之语言概述

    C++语言是广泛使用的程序设计语言之一,因其特有的优势在计算机应用领域占有重要一席. C语言的发展 20世纪70年代初,贝尔实验室的Dennis Richie 等人在B语言基础上开发出C语言,最初是作 ...

  2. 关于Android开发环境的演变

    是不是我天生就不适合安装软件——经过eclipse.jdk.Android Studio的历次安装,我发觉自己似乎永远都装不好.去年eclipse断断续续装了三四天,那时希望能附加C++的软件包,却始 ...

  3. 常用的php数组函数

    以下是自己比较常用的数组函数 数组元素增加减少array_pusharray_poparray_shiftarray_unshift array_splice  (对数组的增删改) array_sli ...

  4. 1.4《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)——编辑命令

    在编辑模式中,命令行包括几个重复之前命令的功能.这些以及其他很多命令功能时常设计键盘上的特殊键,所以给出Table 1作为参考,给出了许多键在典型的Macintosh键盘上的标记符号.若你的键盘不太一 ...

  5. Python面向对象之异常捕获(一)-----抛出一个异常

    大部分的异常都继承自Exception这个类(而这个类有继承自BaseException这个类) 常见的异常 ValueError TypeError IndexError 抛出一个异常 下面这个类的 ...

  6. 20155328 网络攻防 实验五:MSF基础应用

    20155328 网络攻防 实验五:MSF基础应用 实践内容及过程记录 一.Windows服务渗透攻击----ms08_067 攻击机:kali 靶机:WindowsXP(英文版) 第一步,分别查看攻 ...

  7. Luogu P2483 【模板】k短路([SDOI2010]魔法猪学院)

    说实话,看到这道题的洛谷评级我傻了(传说中的最高难度) 然后看完题目才确定这真的是一道k短路的裸题. 也就敲了个A*吧,15分钟竟然没有调试一遍过. 欧洲玄学. 看题目,主要是找几条从1走到n的路加起 ...

  8. P4385 [COCI2009]Dvapravca

    首先特判掉蓝点数量\(<2\)的情况.没有蓝点答案就是\(n\),有一个蓝点可以枚举一个红点,选择过这个蓝点和红点的一条线和在无穷远处的平行线(即这条线对应的两个半平面). 这里认为过一个点是与 ...

  9. Django实现websocket完成实时通讯、聊天室、在线客服等

    一 什么是Websocket WebSocket是一种在单个TCP连接上进行全双工通信的协议 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在WebS ...

  10. Spring Boot (十三): Spring Boot 小技巧

    一些 Spring Boot 小技巧.小知识点 初始化数据 我们在做测试的时候经常需要初始化导入一些数据,如何来处理呢?会有两种选择,一种是使用 Jpa,另外一种是 Spring JDBC .两种方式 ...