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;
}

浙公网安备 33010602011771号