【JZOJ 省選模擬】6700.得分(score )

題目

Description
在這裏插入圖片描述

Input
在這裏插入圖片描述

Output
在這裏插入圖片描述

Sample Input
樣例 1 輸入:
3
4 3 10
1 1 8

樣例 2 輸入:
4
7 20 15 10
7 20 15 10

Sample Output
樣例 1 輸出:
0.62500000000

樣例 2 輸出:
0.31901840491

Data Constraint
在這裏插入圖片描述

Hint
在這裏插入圖片描述

思路

考試的時候精度沒弄好,少了30
首先有一個比較顯然的結論:排序一定是按ai/ti排序的(感受一下)
有了這個結論後我們就可以預處理出一件事情最早做完的時間和最晚做完的時間。
於是我們二分一個c,只要滿足Vilatest<VjearliestV_{i_{latest}}<V_{j_{earliest}}即可

代碼

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+77;
int n;
int st[N],tp;
ll T;
struct P 
{
	ll p,t,tmin,tmax,sum;
	int fp;
}p[N];
bool cmp(P a,P b)
{
	return a.p*b.t>b.p*a.t;
}
bool cmpp(P a,P b) 
{
	return a.p<b.p;
}
bool check(double x) 
{
	double mx=0,tmx=0;
	for(int i=1; i<=n; i++) 
	{
		if(p[i].p != p[i-1].p) mx=tmx;
		if((1-x*p[i].tmax/T)*p[i].p<mx) return 0;
		tmx=max(tmx,(1-x*p[i].tmin/T)*p[i].p);
	}
	return 1;
}
int main()
{
	freopen("score.in","r",stdin); freopen("score.out","w",stdout);
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&st[i]),p[i].p=st[i];
	for(int i=1; i<=n; i++) scanf("%d",&p[i].t),T+=p[i].t;
	sort(st+1,st+1+n),tp=unique(st+1,st+1+n)-st-1;
	for(int i=1; i<=n; i++) p[i].fp=lower_bound(st+1,st+tp+1,p[i].p)-st;
	sort(p+1,p+1+n,cmp);
	for(int i=1; i<=n; i++) p[i].sum=p[i-1].sum+p[i].t;
	for(int i=1,j; i<=n; i=j+1)
	{
		j=i;
		while(j<n&&p[j+1].p*p[i].t==p[i].p*p[j+1].t) j++;
		for(int k=i; k<=j; k++) p[k].tmin=p[i-1].sum+p[k].t,p[k].tmax=p[j].sum;
	}
	sort(p+1,p+1+n,cmpp);
	double l=0,r=1,mid;
	while(r-l>1e-8) check(mid=(l+r)/2)?l=mid:r=mid;
	printf("%.8lf",l);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章