2019.4.13 提高A组 T3 JZOJ 3171 重心

D e s c r i p t i o n Description Description

给你 N N N个长2高 h h h的矩形的质量 m i m_i mi,这N个矩形被放置在笛卡尔坐标系中:

1.矩形的四条边平行于坐标轴;

2.每个矩形下面的水平边的 y y y坐标值互不相同,分别是 0 , h , 2 h , 3 h , . . . , ( n − 1 ) h 0,h,2h,3h,...,(n-1)h 0,h,2h,3h,...,(n1)h

3.最下面的矩形的左下角坐标为(-2,0),即右下角在原点处。

img

一种矩形的摆放方式是稳定的,当且仅当满足:每个矩形上面的所有矩形的 x x x重心跟该矩形的 x x x中点相距不超过1。上面左图是不稳定的而右图是稳定的。

给你 n n n个矩形的质量,要求在不改变矩形的上下顺序的前提下找到一种稳定的摆放方式,同时输出所有稳定摆放方式中最右边矩形右下角 x x x坐标的最大值。

数据范围: n ≤ 3 × 1 0 5 n\leq 3\times 10^5 n3×105


S o l u t i o n Solution Solution

首先若 x x x满足要求,则 x − 1 x-1 x1也满足要求,二分答案转判定即可,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

但实际上,它的公式已经给出,假设我们不考虑稳定,直接套公式即可,若考虑稳定,只需要判断距离是否超过即可,时间复杂度 O ( n ) O(n) O(n)


O ( n l o g n )      C o d e O(nlogn)\ \ \ \ Code O(nlogn)    Code

#include
#include
#include
#define eps 1e-9
using namespace std;int n;
long long m[300001],s[300001];
double l,r,mid;
inline long long read()
{
    char c;long long f=0,d=1;
    while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
    while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
    return d*f;
}
inline bool check(double x)
{
	double nowc=1e9;
	for(register int i=n;i>1;i--) 
	 nowc=min((nowc*s[i+1]+m[i]*(nowc-1))/s[i],((x-2)*s[i+1]+(x-1)*m[i])/s[i]);
	return nowc<=0;
}
signed main()
{
	n=read();
	for(register int i=1;i<=n;i++) m[i]=read();
	for(register int i=n;i>0;i--) s[i]=s[i+1]+m[i];
	l=0;r=n;
	for(mid=n/2;r-l>eps;mid=(l+r)/2.0) 
	if(check(mid)) l=mid;else r=mid;
	printf("%0.6f",l);
}

O ( n )      C o d e O(n)\ \ \ \ Code O(n)    Code

#include
#include
#include
using namespace std;int n;
long long m[300001];
double ans,s;
inline long long read()
{
    char c;long long f=0,d=1;
    while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
    while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
    return d*f;
}
signed main()
{
	n=read();
	for(register int i=1;i<=n;i++) m[i]=read();
	for(register int i=n;i>1;i--) 
	{
		s+=m[i];
		ans=max(m[i]/s+ans,2-m[i]/s);
	}
	printf("%.7lf",ans);
}

你可能感兴趣的:(二分,模拟)