jzoj3171-[GDOI2013模拟4]重心【真·物理,二分】

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/89282845

正题


题目大意

若干个长2高1的长方形且有不同的质量。
对于若干个矩形的重心定义为 m i x i m i \frac{\sum m_i*x_i}{\sum m_i}
要求每个矩形上面的所有矩形的x重心跟该矩形的x中点相距不超过1。
最底下的矩阵的右下角摆放在 ( 2 , 0 ) (-2,0) 的位置求最上面最右能到多远。


解题思路

我们二分答案,然后只要最后重心能到0或以内就可以了。
定义 s i = j = i + 1 n m j s_i=\sum_{j=i+1}^nm_j
从上到下摆放,先假设第一个摆放到无限远也就是重心 G = G=\infty
然后首先我们可以计算出如果往最右拜访重心会到达哪里,
也就是 ( G s i + m i ( G 1 ) ) / ( s i + m i ) (G*s_i+m_i*(G-1))/(s_i+m_i)
但是如果我们发现这时候已经不可以稳定了也就是
G ( s i + m i ) > ( l i m 2 ) s i + ( l i m 1 ) m i G*(s_i+m_i)>(lim-2)*s_i+(lim-1)*m_i
那么我们就整体向左边移动使得
G = ( ( l i m 2 ) s i + ( l i m 1 ) m i ) / ( s i + m i ) G=((lim-2)*s_i+(lim-1)*m_i)/(s_i+m_i)
时间复杂度 O ( n   l o g   ( n 1 0 6 ) ) O(n\ log\ (n*10^6))


c o d e code

#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const double eps=1e-9;
const ll N=310000;
ll n,m[N],s[N];
bool check(double lim)
{
	double G=1e9;
	for(ll i=n;i>=2;i--){
		G=(G*s[i]+m[i]*(G-1))/(s[i]+m[i]);
		if(G*(s[i]+m[i])>(lim-2)*s[i]+(lim-1)*m[i])
		  G=((lim-2)*s[i]+(lim-1)*m[i])/(s[i]+m[i]);
	}
	return G<=0;
}
int main()
{
	scanf("%lld",&n);
	for(ll i=1;i<=n;i++)
		scanf("%lld",&m[i]);
	for(ll i=n-1;i;i--)
		s[i]=s[i+1]+m[i+1];
	double l=0,r=n;
	while(r-l>eps){
		double mid=(r+l)/2;
		if(check(mid)) l=mid;
		else r=mid;
	}
	printf("%.9lf",l);
} 

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/89282845
今日推荐