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

太长懒得写了。。总之就是个斜率优化DP,然后有奇怪性质

原题解

基本能猜到定理八,十至今没理解QAQ

用前八个定理写了一份被卡精度的代码。就是DP的时候记决策点,然后最后用决策点算答案即可。但DP过程本身精度损得厉害,所以有些点过不了。

 // This is an empty program with decimal lib

 #include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
//using namespace std; // ---------- decimal lib start ---------- const int PREC = ; class Decimal {
public:
Decimal();
Decimal(const std::string &s);
Decimal(const char *s);
Decimal(int x);
Decimal(long long x);
Decimal(double x); bool is_zero() const; // p (p > 0) is the number of digits after the decimal point
std::string to_string(int p) const;
double to_double() const; friend Decimal operator + (const Decimal &a, const Decimal &b);
friend Decimal operator + (const Decimal &a, int x);
friend Decimal operator + (int x, const Decimal &a);
friend Decimal operator + (const Decimal &a, long long x);
friend Decimal operator + (long long x, const Decimal &a);
friend Decimal operator + (const Decimal &a, double x);
friend Decimal operator + (double x, const Decimal &a); friend Decimal operator - (const Decimal &a, const Decimal &b);
friend Decimal operator - (const Decimal &a, int x);
friend Decimal operator - (int x, const Decimal &a);
friend Decimal operator - (const Decimal &a, long long x);
friend Decimal operator - (long long x, const Decimal &a);
friend Decimal operator - (const Decimal &a, double x);
friend Decimal operator - (double x, const Decimal &a); friend Decimal operator * (const Decimal &a, int x);
friend Decimal operator * (int x, const Decimal &a); friend Decimal operator / (const Decimal &a, int x); friend bool operator < (const Decimal &a, const Decimal &b);
friend bool operator > (const Decimal &a, const Decimal &b);
friend bool operator <= (const Decimal &a, const Decimal &b);
friend bool operator >= (const Decimal &a, const Decimal &b);
friend bool operator == (const Decimal &a, const Decimal &b);
friend bool operator != (const Decimal &a, const Decimal &b); Decimal & operator += (int x);
Decimal & operator += (long long x);
Decimal & operator += (double x);
Decimal & operator += (const Decimal &b); Decimal & operator -= (int x);
Decimal & operator -= (long long x);
Decimal & operator -= (double x);
Decimal & operator -= (const Decimal &b); Decimal & operator *= (int x); Decimal & operator /= (int x); friend Decimal operator - (const Decimal &a); // These can't be called
friend Decimal operator * (const Decimal &a, double x);
friend Decimal operator * (double x, const Decimal &a);
friend Decimal operator / (const Decimal &a, double x);
Decimal & operator *= (double x);
Decimal & operator /= (double x); private:
static const int len = PREC / + ;
static const int mo = ; static void append_to_string(std::string &s, long long x); bool is_neg;
long long integer;
int data[len]; void init_zero();
void init(const char *s);
}; Decimal::Decimal() {
this->init_zero();
} Decimal::Decimal(const char *s) {
this->init(s);
} Decimal::Decimal(const std::string &s) {
this->init(s.c_str());
} Decimal::Decimal(int x) {
this->init_zero(); if (x < ) {
is_neg = true;
x = -x;
} integer = x;
} Decimal::Decimal(long long x) {
this->init_zero(); if (x < ) {
is_neg = true;
x = -x;
} integer = x;
} Decimal::Decimal(double x) {
this->init_zero(); if (x < ) {
is_neg = true;
x = -x;
} integer = (long long)x;
x -= integer; for (int i = ; i < len; i++) {
x *= mo;
if (x < ) x = ;
data[i] = (int)x;
x -= data[i];
}
} void Decimal::init_zero() {
is_neg = false;
integer = ;
memset(data, , len * sizeof(int));
} bool Decimal::is_zero() const {
if (integer) return false;
for (int i = ; i < len; i++) {
if (data[i]) return false;
}
return true;
} void Decimal::init(const char *s) {
this->init_zero(); is_neg = false;
integer = ; // find the first digit or the negative sign
while (*s != ) {
if (*s == '-') {
is_neg = true;
++s;
break;
} else if (*s >= && *s <= ) {
break;
}
++s;
} // read the integer part
while (*s >= && *s <= ) {
integer = integer * + *s - ;
++s;
} // read the decimal part
if (*s == '.') {
int pos = ;
int x = mo / ; ++s;
while (pos < len && *s >= && *s <= ) {
data[pos] += (*s - ) * x;
++s;
x /= ;
if (x == ) {
++pos;
x = mo / ;
}
}
}
} void Decimal::append_to_string(std::string &s, long long x) {
if (x == ) {
s.append(, );
return;
} char _[];
int cnt = ;
while (x) {
_[cnt++] = x % ;
x /= ;
}
while (cnt--) {
s.append(, _[cnt] + );
}
} std::string Decimal::to_string(int p) const {
std::string ret; if (is_neg && !this->is_zero()) {
ret = "-";
} append_to_string(ret, this->integer); ret.append(, '.'); for (int i = ; i < len; i++) {
// append data[i] as "%09d"
int x = mo / ;
int tmp = data[i];
while (x) {
ret.append(, + tmp / x);
tmp %= x;
x /= ;
if (--p == ) {
break;
}
}
if (p == ) break;
} if (p > ) {
ret.append(p, '');
} return ret;
} double Decimal::to_double() const {
double ret = integer; double k = 1.0;
for (int i = ; i < len; i++) {
k /= mo;
ret += k * data[i];
} if (is_neg) {
ret = -ret;
} return ret;
} bool operator < (const Decimal &a, const Decimal &b) {
if (a.is_neg != b.is_neg) {
return a.is_neg && (!a.is_zero() || !b.is_zero());
} else if (!a.is_neg) {
// a, b >= 0
if (a.integer != b.integer) {
return a.integer < b.integer;
}
for (int i = ; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] < b.data[i];
}
}
return false;
} else {
// a, b <= 0
if (a.integer != b.integer) {
return a.integer > b.integer;
}
for (int i = ; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] > b.data[i];
}
}
return false;
}
} bool operator > (const Decimal &a, const Decimal &b) {
if (a.is_neg != b.is_neg) {
return !a.is_neg && (!a.is_zero() || !b.is_zero());
} else if (!a.is_neg) {
// a, b >= 0
if (a.integer != b.integer) {
return a.integer > b.integer;
}
for (int i = ; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] > b.data[i];
}
}
return false;
} else {
// a, b <= 0
if (a.integer != b.integer) {
return a.integer < b.integer;
}
for (int i = ; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] < b.data[i];
}
}
return false;
}
} bool operator <= (const Decimal &a, const Decimal &b) {
if (a.is_neg != b.is_neg) {
return a.is_neg || (a.is_zero() && b.is_zero());
} else if (!a.is_neg) {
// a, b >= 0
if (a.integer != b.integer) {
return a.integer < b.integer;
}
for (int i = ; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] < b.data[i];
}
}
return true;
} else {
// a, b <= 0
if (a.integer != b.integer) {
return a.integer > b.integer;
}
for (int i = ; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] > b.data[i];
}
}
return true;
}
} bool operator >= (const Decimal &a, const Decimal &b) {
if (a.is_neg != b.is_neg) {
return !a.is_neg || (a.is_zero() && b.is_zero());
} else if (!a.is_neg) {
// a, b >= 0
if (a.integer != b.integer) {
return a.integer > b.integer;
}
for (int i = ; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] > b.data[i];
}
}
return true;
} else {
// a, b <= 0
if (a.integer != b.integer) {
return a.integer < b.integer;
}
for (int i = ; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) {
return a.data[i] < b.data[i];
}
}
return true;
}
} bool operator == (const Decimal &a, const Decimal &b) {
if (a.is_zero() && b.is_zero()) return true;
if (a.is_neg != b.is_neg) return false;
if (a.integer != b.integer) return false;
for (int i = ; i < Decimal::len; i++) {
if (a.data[i] != b.data[i]) return false;
}
return true;
} bool operator != (const Decimal &a, const Decimal &b) {
return !(a == b);
} Decimal & Decimal::operator += (long long x) {
if (!is_neg) {
if (integer + x >= ) {
integer += x;
} else {
bool last = false;
for (int i = len - ; i >= ; i--) {
if (last || data[i]) {
data[i] = mo - data[i] - last;
last = true;
} else {
last = false;
}
}
integer = -x - integer - last;
is_neg = true;
}
} else {
if (integer - x >= ) {
integer -= x;
} else {
bool last = false;
for (int i = len - ; i >= ; i--) {
if (last || data[i]) {
data[i] = mo - data[i] - last;
last = true;
} else {
last = false;
}
}
integer = x - integer - last;
is_neg = false;
}
}
return *this;
} Decimal & Decimal::operator += (int x) {
return *this += (long long)x;
} Decimal & Decimal::operator -= (int x) {
return *this += (long long)-x;
} Decimal & Decimal::operator -= (long long x) {
return *this += -x;
} Decimal & Decimal::operator /= (int x) {
if (x < ) {
is_neg ^= ;
x = -x;
} int last = integer % x;
integer /= x; for (int i = ; i < len; i++) {
long long tmp = 1LL * last * mo + data[i];
data[i] = tmp / x;
last = tmp - 1LL * data[i] * x;
} if (is_neg && integer == ) {
int i;
for (i = ; i < len; i++) {
if (data[i] != ) {
break;
}
}
if (i == len) {
is_neg = false;
}
} return *this;
} Decimal & Decimal::operator *= (int x) {
if (x < ) {
is_neg ^= ;
x = -x;
} else if (x == ) {
init_zero();
return *this;
} int last = ;
for (int i = len - ; i >= ; i--) {
long long tmp = 1LL * data[i] * x + last;
last = tmp / mo;
data[i] = tmp - 1LL * last * mo;
}
integer = integer * x + last; return *this;
} Decimal operator - (const Decimal &a) {
Decimal ret = a;
// -0 = 0
if (!ret.is_neg && ret.integer == ) {
int i;
for (i = ; i < Decimal::len; i++) {
if (ret.data[i] != ) break;
}
if (i < Decimal::len) {
ret.is_neg = true;
}
} else {
ret.is_neg ^= ;
}
return ret;
} Decimal operator + (const Decimal &a, int x) {
Decimal ret = a;
return ret += x;
} Decimal operator + (int x, const Decimal &a) {
Decimal ret = a;
return ret += x;
} Decimal operator + (const Decimal &a, long long x) {
Decimal ret = a;
return ret += x;
} Decimal operator + (long long x, const Decimal &a) {
Decimal ret = a;
return ret += x;
} Decimal operator - (const Decimal &a, int x) {
Decimal ret = a;
return ret -= x;
} Decimal operator - (int x, const Decimal &a) {
return -(a - x);
} Decimal operator - (const Decimal &a, long long x) {
Decimal ret = a;
return ret -= x;
} Decimal operator - (long long x, const Decimal &a) {
return -(a - x);
} Decimal operator * (const Decimal &a, int x) {
Decimal ret = a;
return ret *= x;
} Decimal operator * (int x, const Decimal &a) {
Decimal ret = a;
return ret *= x;
} Decimal operator / (const Decimal &a, int x) {
Decimal ret = a;
return ret /= x;
} Decimal operator + (const Decimal &a, const Decimal &b) {
if (a.is_neg == b.is_neg) {
Decimal ret = a;
bool last = false;
for (int i = Decimal::len - ; i >= ; i--) {
ret.data[i] += b.data[i] + last;
if (ret.data[i] >= Decimal::mo) {
ret.data[i] -= Decimal::mo;
last = true;
} else {
last = false;
}
}
ret.integer += b.integer + last;
return ret;
} else if (!a.is_neg) {
// a - |b|
return a - -b;
} else {
// b - |a|
return b - -a;
}
} Decimal operator - (const Decimal &a, const Decimal &b) {
if (!a.is_neg && !b.is_neg) {
if (a >= b) {
Decimal ret = a;
bool last = false;
for (int i = Decimal::len - ; i >= ; i--) {
ret.data[i] -= b.data[i] + last;
if (ret.data[i] < ) {
ret.data[i] += Decimal::mo;
last = true;
} else {
last = false;
}
}
ret.integer -= b.integer + last;
return ret;
} else {
Decimal ret = b;
bool last = false;
for (int i = Decimal::len - ; i >= ; i--) {
ret.data[i] -= a.data[i] + last;
if (ret.data[i] < ) {
ret.data[i] += Decimal::mo;
last = true;
} else {
last = false;
}
}
ret.integer -= a.integer + last;
ret.is_neg = true;
return ret;
}
} else if (a.is_neg && b.is_neg) {
// a - b = (-b) - (-a)
return -b - -a;
} else if (a.is_neg) {
// -|a| - b
return -(-a + b);
} else {
// a - -|b|
return a + -b;
}
} Decimal operator + (const Decimal &a, double x) {
return a + Decimal(x);
} Decimal operator + (double x, const Decimal &a) {
return Decimal(x) + a;
} Decimal operator - (const Decimal &a, double x) {
return a - Decimal(x);
} Decimal operator - (double x, const Decimal &a) {
return Decimal(x) - a;
} Decimal & Decimal::operator += (double x) {
*this = *this + Decimal(x);
return *this;
} Decimal & Decimal::operator -= (double x) {
*this = *this - Decimal(x);
return *this;
} Decimal & Decimal::operator += (const Decimal &b) {
*this = *this + b;
return *this;
} Decimal & Decimal::operator -= (const Decimal &b) {
*this = *this - b;
return *this;
} // ---------- decimal lib end ---------- int qread()
{
char c; int s=; while ((c=getchar())<'' || c>'');
do s=s*+c-''; while ((c=getchar())>='' && c<=''); return s;
}
#define lld Decimal
#define ld long double
int n,m,P;
#define maxn 8011
int a[maxn],sum[maxn];
ld f[][maxn]; short cur=,p[maxn][maxn];
short sta[maxn],top=; struct Queue
{
int x; ld y;
ld operator * (const Queue b) const {return (y-b.y)/(x-b.x);}
}que[maxn]; int head,tail; ld calc(int i,int j) {return (f[cur][j]+sum[i]-sum[j])/(i-j+);} int main()
{
n=qread(); m=qread(); P=qread();
int a0=qread(); for (int i=;i<n;i++) a[i]=qread();
n--; {int m=; for (int i=;i<=n;i++) if (a[i]>a0) a[++m]=a[i]; n=m;}
std::sort(a+,a++n); for (int i=;i<=n;i++) sum[i]=sum[i-]+a[i]; for (int i=;i<=n;i++) f[][i]=a0;
ld ans=a0; short xx=,yy=n;
for (int i=,to=std::min(n,m);i<=to;i++)
{
memset(f[cur^],,sizeof(f[cur^]));
f[cur^][i]=(f[cur][i-]+a[i])/; p[i][i]=i-;
if (ans<f[cur^][i]) ans=f[cur^][i],xx=i,yy=i;
head=tail=; que[tail++]=(Queue){i-,sum[i-]-f[cur][i-]};
for (int j=i+;j<=n;j++)
{
Queue u=(Queue){j-,sum[j-]-f[cur][j-]};
while (head<tail- && que[tail-]*que[tail-]>u*que[tail-]) tail--;
que[tail++]=u;
while (head<tail- && calc(j,que[head].x+)<calc(j,que[head+].x+)) head++;
f[cur^][j]=calc(j,que[head].x+); p[i][j]=que[head].x+;
if (ans<f[cur^][j]) ans=f[cur^][j],xx=i,yy=j;
}
cur^=;
} lld Ans=lld(a0);
for (;xx;yy=p[xx][yy],xx--) sta[++top]=yy; sta[++top]=yy;
for (int i=top;i>;i--) Ans=(Ans+(sum[sta[i-]]-sum[sta[i]]))/(sta[i-]-sta[i]+); std::string s=Ans.to_string(P+);
std::cout<<s<<std::endl;
return ;
}

*UOJ#223. 【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. [Noi2016]国王饮水记

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

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

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

  6. BZOJ4654 NOI2016国王饮水记(动态规划+三分)

    有很多比较显然的性质.首先每个城市(除1外)至多被连通一次,否则没有意义.其次将城市按水位从大到小排序后,用以连通的城市集合是一段前缀,并且不应存在比1城市还小的.然后如果确定了选取的城市集合,每次选 ...

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

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

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

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

  9. [NOI 2016]国王饮水记

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

随机推荐

  1. 【图论】[USACO]控制公司 Controlling Companies

    玄妙的搜索 题目描述 有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分.(此处略去一句废话)据说,如果至少满足了以下三个条件之一,公司A就可以控制公司B了: 公司A = 公司B ...

  2. MySQL - CASE WHEN ... THEN ... ELSE ... END语句

    范例: CASE WHEN p.allow_over = 1 THEN p.allow_over_capital ELSE 0 END

  3. Mysql的一些纪要

    unsigned 整型的每一种都分无符号(unsigned)和有符号(signed)两种类型(float和double总是带符号的),在默认情况下声明的整型变量都是有符号的类型(char有点特别),如 ...

  4. 了解并使用springAOP(面向切面编程)

    Aop是干嘛的为什么要使用它 在业务系统中,总有一些散落,渗透到系统的各处且不得不处理的事情,这些穿插在既定业务中的操作就是所谓的“横切逻辑”,也称切面, 我们怎样才不受这些附加要求的干扰,专心于真正 ...

  5. linux 的安装

    3linux 软件安装 3.1 vm ware 软件安装 双击VMware-workstation-full-10.0.2-1744117.1398244508.exe 单击下一步 单击下一步 选择典 ...

  6. A1025 PAT Ranking (25)(25 分)

    A1025 PAT Ranking (25)(25 分) Programming Ability Test (PAT) is organized by the College of Computer ...

  7. python数据模型(特殊方法)

    python中的全部特殊方法 本部分内容可以参考官方网址 python中一共有83个特殊方法,其中47个用于算术运算.位运算和比较操作.我根据<流畅的python>中的整理,摘录如下两个表 ...

  8. Kubespray部署Kubernetes 1.13.0(使用本地镜像仓库)

    1. 下载kubespray # git clone https://github.com/kubernetes-sigs/kubespray.git # cd kubespray # pip ins ...

  9. laravel5.2总结--本地化以及常量的使用

    1.本地化 Laravel 的本地化功能提供方便的方法来获取多语言的字符串,让你的网站可以简单的支持多语言. 语言包存放在 resources/lang 文件夹的文件里.每一个子目录应该对应一种语言 ...

  10. 59、佳博wifi打印机怎么配置

    1.去这里下载配置软件(注意,需要再windows下进行)http://pan.baidu.com/s/1bn1y4FX,并解压安装程序 2.连上wifi打印机的热点,比如说佳博打印机的默认为Gpri ...