P12519「MSTOI-R1」热开水 题解

题目链接

因为玩的天数越多 rks 也会越多或不变,所以答案是具有单调性的,故考虑二分答案。

接下来思考在已知天数的情况下求 rks。可以用优先队列维护最高的 \(5\) 首单曲 rks,变量维护最大 \(acc=100\%\) 曲的 rks。枚举每一首曲计算出新的 rks,分类讨论,\(<70\%\) 的直接不要,否则加入优先队列,如果 \(=100\%\) 再取最大值。最后取出队头的 \(5\) 首就可以计算总 rks。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e5+100;
int l=-1,r=10001,mid,n;
double m,a[N],b[N],c[N],st[N];
double retain2(double x)
{
	int y;
	double z;
	x*=100;
	y=x;
	z=y/100.0;
	return z;
}
bool check(int x)
{
	priority_queue<double> pq;
	double acc,rks,sum,ma=st[5];
	for(int i=1;i<=4;i++) pq.push(st[i]);
	for(int i=1;i<=n;i++)
	{
		acc=min(100.0,retain2(a[i]+retain2((x-1)*b[i])));
		if(acc>=70) rks=retain2(retain2(retain2((acc-55)/45.0)*retain2((acc-55)/45.0))*c[i]);
		else rks=0;
		if(acc==100) ma=max(ma,rks);
		if(x>0) pq.push(rks);
	}
	sum=ma;
	for(int i=1;i<=4;i++)
	{
		sum+=pq.top();
		pq.pop();
	}
	sum=retain2(sum/5.0);
	return sum>=m;
}
int main()
{
	scanf("%d%lf",&n,&m);
	for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i],&b[i],&c[i]);
	for(int i=1;i<=5;i++) scanf("%lf",&st[i]);
	while(l+1<r)
	{
		mid=(l+r)>>1;
		if(check(mid)) r=mid;
		else l=mid;
	}
	if(r==10001) r=-1;
	printf("%d",r);
	return 0;
}
posted @ 2025-06-14 14:27  MinimumSpanningTree  阅读(3)  评论(0)    收藏  举报