题目
题目背景
《Phigros》是一款由 Pigeon Games 开发的音乐节奏游戏,以无轨谱面和独特的判定线玩法为特色。游戏中的音符跟随判定线的移动而变化,考验玩家的反应速度和手眼协调能力。它拥有丰富的曲库,涵盖多种音乐风格,画面精美,视觉效果独特。游戏采用免费模式,不设体力限制,是一款富有创意且具有挑战性的音游。
题目描述
众所周知,
kiwi
\text{kiwi}
kiwi 和
kouki
\text{kouki}
kouki (大佬)非常喜欢打《Phigros》,而《Phigros》的总体 rks(Ranking Score)是衡量一个玩家水平的具体标准,其由众多单个谱面 的 rks 计算得来,每个谱面有定数和准确度 ACC 两个数值。假设你在一张定数为
X
X
X 的谱面打出了
Y
Y
Y 的 ACC,则你的单个谱面 rks 计算公式如下:
r
k
s
=
{
0
Y
<
0.7
(
Y
×
100
−
55
45
)
2
×
X
Y
⩾
0.7
rks=\begin{cases}0&Y<0.7\\(\dfrac{Y \times 100-55}{45})^2 \times X&Y\geqslant0.7\end{cases}
rks=⎩
⎨
⎧0(45Y×100−55)2×XY<0.7Y⩾0.7
而总体 rks 的计算是对所有谱面计算单个谱面的 rks,然后取其中单个谱面 rks 最高的19张谱面加上所有收歌谱面(收歌谱面是指 ACC 为 1 的谱面)中定数最高的那张谱的 rks 的和,对其严格除以 20 ,结果即为总体 rks。 kiwi \text{kiwi} kiwi 给出他所打过的谱面,请你帮 kiwi \text{kiwi} kiwi 算出他的总体 rks,好追上 kouki \text{kouki} kouki。
注意:
单个谱面中 rks 最高的 19 张中可以包含收歌谱面。
计算总体 rks 时,无论当前谱面总数是否达到20,均严格除以20。
输入输出格式
【输入格式】
测试用例的第一行包含一个整数 n n n 。表示有 n n n 个曲目。
接下来 n 行每行先后有一个整数 x x x 和一个两位小数 y y y ,分别表示谱面定数和 Acc 。
【输出格式】
对于每个测试用例,输出一个小数,表示 kiwi \text{kiwi} kiwi 的总体 rks,四舍五入保留两位小数。
数据范围
1 ≤ n ≤ 1 × 1 0 4 1 \le n \le 1 \times 10^4 1≤n≤1×104
1 ≤ x ≤ 17 1 \le x \le 17 1≤x≤17
0 ≤ y ≤ 1 0 \le y \le 1 0≤y≤1
测试样例
input1
20
14 1
4 0.17
15 0.34
16 0.46
15 0.39
10 0.48
7 0.58
3 0.55
9 0.8
2 0.71
15 0.35
6 0.96
11 0.45
16 0.86
3 1
16 0.88
17 0.1
11 0.36
14 0.69
13 0.77
output1
2.92
input2
10
6 1
5 0.53
11 0.97
2 0.18
1 0.09
14 0
10 0.74
17 0.38
1 0.34
1 0.42
output2
1.17
样例说明
在测试样例2中,
kiwi
\text{kiwi}
kiwi 打过的总谱数不足20张,但是他的 总体 rks 计算时,仍为前19张 rks 最高的谱面加上收歌谱面中定数最高的那张谱面的 rks 之和除以20,不足的谱面张数不加入计算 (或视为 rks 为0)。其 rks 为
(
9.58222
+
6
+
1.78272
+
0
+
0
+
0
+
0
+
0
+
0
+
0
+
6
20
)
=
1.17
\left(\dfrac{9.58222+6+1.78272+0+0+0+0+0+0+0+6}{20}\right)=1.17
(209.58222+6+1.78272+0+0+0+0+0+0+0+6)=1.17
思路
根据题面给出的单个谱面 r k s rks rks 计算公式,对每个谱面计算其 r k s rks rks,并将其存入数组中。对数组进行非递减的排序,依题意取前 m i n ( 19 , n ) min(19,n) min(19,n)个值和定数最高的收歌谱面的 r k s rks rks 值求和,对该总和除以 20 20 20 即为结果。时间复杂度为 O ( n ) O(n) O(n)。
代码
#include <bits/stdc++.h>
using namespace std;
void solve()
{
int n;
cin>>n;
vector< double>arr;
double maxding=0;
for(int i=0;i<n;++i)
{
int a;
double b;
cin>>a>>b;
if(b<0.7)arr.push_back(0);
else arr.push_back(pow((b*100-55)/45,2)*a);
if(b==1)maxding=max(maxding,arr[i]);
//cout<<arr[i]<<"\n";
}
sort(arr.begin(),arr.end());
if(n<19)
{
double sum=0;
for(int i=0;i<n;++i)sum+=arr[i];
sum+=maxding;
printf("%.2lf",sum/20);
}
else
{
double sum=0;
for(int i=n-19;i<n;++i)sum+=arr[i];
sum+=maxding;
printf("%.2lf",sum/20);
}
}
int main()
{
int t=1;
//cin>>t;
while(t--)
{
solve();
}
return 0;
}
复杂度分析
时间复杂度
-
读取输入数据:读取 n n n 个曲目的定数和准确度需要 O ( n ) O(n) O(n) 的时间。
-
计算单个谱面 rks:对于每个曲目,根据公式计算其 r k s rks rks 值,这一步需要 O ( n ) O(n) O(n) 的时间。
-
排序 rks 值:将所有 r k s rks rks 值排序需要 O ( n log n ) O(n \log n) O(nlogn) 的时间。
-
选择前 19 个 rks 值:从排序后的数组中选择前 19 个 r k s rks rks 值,需要 O ( 1 ) O(1) O(1) 的时间。
-
求和和输出:计算总和并输出,总共需要 O ( 1 ) O(1) O(1) 的时间。
综上所述,总的时间复杂度为 O ( n log n ) O(n \log n) O(nlogn),排序步骤是主要的时间消耗。
空间复杂度
-
存储 r k s rks rks 值:我们使用了一个大小为 n n n 的数组来存储每个谱面的 r k s rks rks 值,空间复杂度为 O ( n ) O(n) O(n)。
-
其他变量:仅使用了一些常量空间来存储最大定数和其他变量。