zoukankan      html  css  js  c++  java
  • NOI2016 国王饮水记

    NOI2016 国王饮水记

    题意:

    ​ 自己看

    题解:

    ​ 这题是大结论题,推荐这篇博客

    ​ 结论找出来后不难做,但是,他卡你有没有看说明书!!!

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define fo(i,l,r) for(int i=l;i<=r;i++)
    #define of(i,l,r) for(int i=l;i>=r;i--)
    #define fe(i,u) for(int i=head[u];i;i=e[i].next)
    using namespace std;
    typedef long long ll;
    inline void open(const char *s)
    {
    	#ifndef ONLINE_JUDGE
    	char str[20];
    	sprintf(str,"in%s.txt",s);
    	freopen(str,"r",stdin);
    //	sprintf(str,"out%s.txt",s);
    //	freopen(str,"w",stdout);
    	#endif
    }
    inline int rd()
    {
    	static int x,f;
    	x=0;f=1;
    	char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    	return f>0?x:-x;
    }
    
    // ---------- decimal lib start ----------
    
    const int PREC = 3100;
    
    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 / 9 + 1;
    		static const int mo = 1000000000;
    		
    		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 < 0) {
    		is_neg = true;
    		x = -x;
    	}
    	
    	integer = x;
    }
    
    Decimal::Decimal(long long x) {
    	this->init_zero();
    	
    	if (x < 0) {
    		is_neg = true;
    		x = -x;
    	}
    	
    	integer = x;
    }
    
    Decimal::Decimal(double x) {
    	this->init_zero();
    	
    	if (x < 0) {
    		is_neg = true;
    		x = -x;
    	}
    	
    	integer = (long long)x;
    	x -= integer;
    	
    	for (int i = 0; i < len; i++) {
    		x *= mo;
    		if (x < 0) x = 0;
    		data[i] = (int)x;
    		x -= data[i];
    	}
    }
    
    void Decimal::init_zero() {
    	is_neg = false;
    	integer = 0;
    	memset(data, 0, len * sizeof(int));
    }
    
    bool Decimal::is_zero() const {
    	if (integer) return false;
    	for (int i = 0; i < len; i++) {
    		if (data[i]) return false;
    	}
    	return true;
    }
    
    void Decimal::init(const char *s) {
    	this->init_zero();
    	
    	is_neg = false;
    	integer = 0;
    	
    	// find the first digit or the negative sign
    	while (*s != 0) {
    		if (*s == '-') {
    			is_neg = true;
    			++s;
    			break;
    		} else if (*s >= 48 && *s <= 57) {
    			break;
    		}
    		++s;
    	}
    	
    	// read the integer part
    	while (*s >= 48 && *s <= 57) {
    		integer = integer * 10 + *s - 48;
    		++s;
    	}
    	
    	// read the decimal part
    	if (*s == '.') {
    		int pos = 0;
    		int x = mo / 10;
    		
    		++s;
    		while (pos < len && *s >= 48 && *s <= 57) {
    			data[pos] += (*s - 48) * x;
    			++s;
    			x /= 10;
    			if (x == 0) {
    				++pos;
    				x = mo / 10;
    			}
    		}
    	}
    }
    
    void Decimal::append_to_string(std::string &s, long long x) {
    	if (x == 0) {
    		s.append(1, 48);
    		return;
    	}
    	
    	char _[30];
    	int cnt = 0;
    	while (x) {
    		_[cnt++] = x % 10;
    		x /= 10;
    	}
    	while (cnt--) {
    		s.append(1, _[cnt] + 48);
    	}
    }
    
    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(1, '.');
    	
    	for (int i = 0; i < len; i++) {
    		// append data[i] as "%09d"
    		int x = mo / 10;
    		int tmp = data[i];
    		while (x) {
    			ret.append(1, 48 + tmp / x);
    			tmp %= x;
    			x /= 10;
    			if (--p == 0) {
    				break;
    			}
    		}
    		if (p == 0) break;
    	}
    	
    	if (p > 0) {
    		ret.append(p, '0');
    	}
    	
    	return ret;
    }
    
    double Decimal::to_double() const {
    	double ret = integer;
    	
    	double k = 1.0;
    	for (int i = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 = 0; 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 >= 0) {
    			integer += x;
    		} else {
    			bool last = false;
    			for (int i = len - 1; i >= 0; 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 >= 0) {
    			integer -= x;
    		} else {
    			bool last = false;
    			for (int i = len - 1; i >= 0; 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 < 0) {
    		is_neg ^= 1;
    		x = -x;
    	}
    	
    	int last = integer % x;
    	integer /= x;
    	
    	for (int i = 0; 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 == 0) {
    		int i;
    		for (i = 0; i < len; i++) {
    			if (data[i] != 0) {
    				break;
    			}
    		}
    		if (i == len) {
    			is_neg = false;
    		}
    	}
    	
    	return *this;
    }
    
    Decimal & Decimal::operator *= (int x) {
    	if (x < 0) {
    		is_neg ^= 1;
    		x = -x;
    	} else if (x == 0) {
    		init_zero();
    		return *this;
    	}
    	
    	int last = 0;
    	for (int i = len - 1; i >= 0; 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 == 0) {
    		int i;
    		for (i = 0; i < Decimal::len; i++) {
    			if (ret.data[i] != 0) break;
    		}
    		if (i < Decimal::len) {
    			ret.is_neg = true;
    		}
    	} else {
    		ret.is_neg ^= 1;
    	}
    	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 - 1; i >= 0; 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 - 1; i >= 0; i--) {
    				ret.data[i] -= b.data[i] + last;
    				if (ret.data[i] < 0) {
    					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 - 1; i >= 0; i--) {
    				ret.data[i] -= a.data[i] + last;
    				if (ret.data[i] < 0) {
    					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 ----------
    const int N=8010;
    Decimal ans;
    int n,K,p,h[N],q[N],ql,qr,fr[N][20],s[N];
    double f[N][20];
    struct node{
    	double x,y;
    }hh,b[N];
    
    inline double calc(node a,node b){return (b.y-a.y)/(b.x-a.x);}
    inline Decimal gao(int i,int j)
    {
    	if(!j)return Decimal(h[1]);
    	return (gao(fr[i][j],j-1)+Decimal(s[i])-Decimal(s[fr[i][j]]))/(i-fr[i][j]+1);
    }
    
    int main()
    {
    	n=rd();K=rd();p=rd();h[1]=rd();
    	fo(i,2,n){h[i]=rd();if(h[i]<h[1])i--,n--;}
    	sort(h+1,h+n+1);fo(i,1,n)s[i]=s[i-1]+h[i];
    	K=min(K,n);fo(i,1,n)f[i][0]=h[1];
    	int lim=min(K,14);
    	fo(j,1,lim){
    		q[ql=qr=1]=1;b[1].x=0;b[1].y=s[1]-f[1][j-1];
    		fo(i,2,n){
    			hh.x=i;hh.y=s[i];
    			while(ql<qr&&calc(b[q[ql]],hh)<calc(b[q[ql+1]],hh))ql++;
    			b[i].x=i-1;b[i].y=s[i]-f[i][j-1];fr[i][j]=q[ql];
    			f[i][j]=s[i]-s[q[ql]]+f[q[ql]][j-1];f[i][j]/=(double)(i-q[ql]+1);
    			while(ql<qr&&calc(b[q[qr-1]],b[q[qr]])>calc(b[q[qr]],b[i]))qr--;
    			q[++qr]=i;
    		}
    	}
    	int m=n-K+lim;
    	double mx=0;int pos;
    	fo(j,0,lim)if(f[m][j]>mx)mx=f[m][j],pos=j;
    	ans=gao(m,pos);
    	fo(i,m+1,n)ans=(ans+h[i])/2;
    	cout<<ans.to_string(p+3);
    	return 0;
    }
    
  • 相关阅读:
    hdu 2203
    hdu 3081
    hdu 4240 最大流量路径
    b_vj_Fiber Network(floyd思想+状态压缩)
    b_vj_Corn Fields(预处理行的状态、合法状态+枚举当前行与上一行的状态)
    b_vj_Hackers' Crackdown(预处理所有集合+检查合法集合后进行状态转移)
    b_vj_Count Color(线段树+二进制表示颜色)
    b_vj_K-th Number(二分+线段树)
    b_lg_火烧赤壁(讨论完全覆盖/部分覆盖)
    b_hdu_Ping pong(树状数组+乘法原理)
  • 原文地址:https://www.cnblogs.com/JackyhhJuRuo/p/9837312.html
Copyright © 2011-2022 走看看