*UOJ#223. 【NOI2016】国王饮水记
$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】国王饮水记的更多相关文章
- [UOJ#223][BZOJ4654][Noi2016]国王饮水记
[UOJ#223][BZOJ4654][Noi2016]国王饮水记 试题描述 跳蚤国有 n 个城市,伟大的跳蚤国王居住在跳蚤国首都中,即 1 号城市中.跳蚤国最大的问题就是饮水问题,由于首都中居住的跳 ...
- luogu P1721 [NOI2016]国王饮水记 斜率优化dp 贪心 决策单调性
LINK:国王饮水记 看起来很不可做的样子. 但实际上还是需要先考虑贪心. 当k==1的时候 只有一次操作机会.显然可以把那些比第一个位置小的都给扔掉. 然后可以得知剩下序列中的最大值一定会被选择. ...
- BZOJ4654/UOJ223 [Noi2016]国王饮水记
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- [Noi2016]国王饮水记
来自FallDream的博客,未经允许,请勿转载,谢谢. 跳蚤国有 n 个城市,伟大的跳蚤国王居住在跳蚤国首都中,即 1 号城市中.跳蚤国最大的问题就是饮水问题,由于首都中居住的跳蚤实在太多,跳蚤国王 ...
- uoj233/BZOJ4654/洛谷P1721 [Noi2016]国王饮水记 【dp + 斜率优化】
题目链接 uoj233 题解 下面不加证明地给出几个性质: 小于\(h[1]\)的城市一定是没用的 任何城市联通包含\(1\)且只和\(1\)联通一次 联通顺序从小到大最优 单个联通比多个一起联通要优 ...
- BZOJ4654 NOI2016国王饮水记(动态规划+三分)
有很多比较显然的性质.首先每个城市(除1外)至多被连通一次,否则没有意义.其次将城市按水位从大到小排序后,用以连通的城市集合是一段前缀,并且不应存在比1城市还小的.然后如果确定了选取的城市集合,每次选 ...
- P1721 [NOI2016] 国王饮水记 题解
蒟蒻的第一篇黑题题解,求过. 题目链接 题意描述 这道题用简洁的话来说,就是: 给你 \(n\) 个数字,你可以让取其中任意若干个数字,每次操作,都会使所有取的数字变为取的数字的平均数,并且你最多只能 ...
- 【BZOJ4654】【NOI2016】国王饮水记(动态规划,斜率优化)
[BZOJ4654][NOI2016]国王饮水记(动态规划,斜率优化) 题面 BZOJ 洛谷 题解 首先肯定是找性质. 明确一点,比\(h_1\)小的没有任何意义. 所以我们按照\(h\)排序,那么\ ...
- [NOI 2016]国王饮水记
Description 题库链接 给出 \(n\) 个水杯,每个水杯装有不同高度的水 \(h_i\) ,每次可以指定任意多水杯用连通器连通后断开,问不超过 \(k\) 次操作之后 \(1\) 号水杯的 ...
随机推荐
- 51nod——2476 小b和序列(预处理 思维)
对于每一个元素,预处理出它作为最小值,两边可以作用到的最大位置.比如下标∈[0,8]的这个数组:1 8 6 2 5 4 3 8 7,1可以作用到所有区间,2可以作用到区间[1,8],第一个8可以作用到 ...
- 1045: [HAOI2008] 糖果传递
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4897 Solved: 2457[Submit][Status][Discuss] Descript ...
- js函数带括号和不带括号赋给对象属性的区别
注意: 1.js为对象添加函数时,不要在函数后面加().一旦加了括号是表示将函数的返回值赋给对象的属性. 例:function test(){ document.writeln("我是js函 ...
- php扩展开发-实现一个简易的哈希表
从一个简易的哈希表入手,会让你更好的理解php的哈希表,他们的本质是一样的,只是php的哈希表做了更多的功能扩展,php的哈希表是php语言的一个重要核心,大量的内核代码使用到哈希表. #includ ...
- Ubuntu12.04下YouCompleteMe安装教程(部分)
1.通过源码编译安装VIM 开发中使用的是Ubuntu 12.04 LTS,通过sudo apt-get install vim安装的版本较低,不支持YCM,所以,用源码编译并安装最新的Vim. 卸载 ...
- linux安装vmware出现kernel-header问题
查看日志文件, cat /tmp/vmware-xiuyuan/vmware-modconfig-9996.log | more在日志文件中有这么几行:Setting header path for ...
- 使用Hbase快照将数据输出到互联网区测试环境的临时Hbase集群
通过snapshot对内网测试环境Hbase生产集群的全量数据(包括原始数据和治理后数据)复制到互联网Hbase临时集群.工具及原理: 1) Hbase自带镜像导出工具(snapsho ...
- HDU1301 Jungle Roads
Jungle Roads The Head Elder of the tropical island of Lagrishan has a problem. A burst of foreign ai ...
- python资源大全2
原文链接 网络 Scapy, Scapy3k: 发送,嗅探,分析和伪造网络数据包.可用作交互式包处理程序或单独作为一个库. pypcap, Pcapy, pylibpcap: 几个不同 libpcap ...
- 笔记-算法-KMP算法
笔记-算法-KMP算法 1. KMP算法 KMP算法是一种改进的字符串匹配算法,KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的.具体实现就是实现一 ...