Dirt Ratio
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 384 Accepted Submission(s): 120
Special Judge
Problem Description
In ACM/ICPC contest, the ''Dirt Ratio'' of a team is calculated in the following way. First let's ignore all the problems the team didn't pass, assume the team passed
X
problems during the contest, and submitted
Y
times for these problems, then the ''Dirt Ratio'' is measured as
XY
. If the ''Dirt Ratio'' of a team is too low, the team tends to cause more penalty, which is not a good performance.
Picture from MyICPC
Little Q is a coach, he is now staring at the submission list of a team. You can assume all the problems occurred in the list was solved by the team during the contest. Little Q calculated the team's low ''Dirt Ratio'', felt very angry. He wants to have a talk with them. To make the problem more serious, he wants to choose a continuous subsequence of the list, and then calculate the ''Dirt Ratio'' just based on that subsequence.
Please write a program to find such subsequence having the lowest ''Dirt Ratio''.

Picture from MyICPC
Little Q is a coach, he is now staring at the submission list of a team. You can assume all the problems occurred in the list was solved by the team during the contest. Little Q calculated the team's low ''Dirt Ratio'', felt very angry. He wants to have a talk with them. To make the problem more serious, he wants to choose a continuous subsequence of the list, and then calculate the ''Dirt Ratio'' just based on that subsequence.
Please write a program to find such subsequence having the lowest ''Dirt Ratio''.
Input
The first line of the input contains an integer
T(1≤T≤15)
, denoting the number of test cases.
In each test case, there is an integer n(1≤n≤60000) in the first line, denoting the length of the submission list.
In the next line, there are n positive integers a1,a2,...,an(1≤ai≤n) , denoting the problem ID of each submission.
In each test case, there is an integer n(1≤n≤60000) in the first line, denoting the length of the submission list.
In the next line, there are n positive integers a1,a2,...,an(1≤ai≤n) , denoting the problem ID of each submission.
Output
For each test case, print a single line containing a floating number, denoting the lowest ''Dirt Ratio''. The answer must be printed with an absolute error not greater than
10−4
.
Sample Input
1 5 1 2 1 2 3
Sample Output
0.5000000000HintFor every problem, you can assume its final submission is accepted.
Source
Recommend
思路:赛后看官方题解秒懂。。当时有想过二分答案但没细想下去gg。思路和官方一模一样就不细说了。直接上代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cmath>
#include<queue>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#include<string>
#include<utility>
#include<set>
#include<map>
#include<stack>
#include<vector>
#define maxn 60005
#define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
const double eps = 1e-5;
const int mod = 1e6 + 3;
int n, a[maxn], Left[maxn], vis[maxn], mark[maxn << 2];
double minnum[maxn << 2];
void insert(int l, int r, int index, int now, double x){
if (l == r){
minnum[now] = x*l;
return;
}
int mid = l + r >> 1;
if (mark[now]){
minnum[now << 1] += mark[now];
mark[now << 1] += mark[now];
minnum[now << 1 | 1] += mark[now];
mark[now << 1 | 1] += mark[now];
mark[now] = 0;
}
if (index <= mid)
insert(l, mid, index, now << 1, x);
else
insert(mid + 1, r, index, now << 1 | 1, x);
minnum[now] = min(minnum[now << 1], minnum[now << 1 | 1]);
}
void update(int l1, int r1, int l2, int r2, int now){
if (l2 <= l1&&r2 >= r1){
minnum[now] += 1;
mark[now]++;
return;
}
int mid = l1 + r1 >> 1;
if (mark[now]){
minnum[now << 1] += mark[now];
mark[now << 1] += mark[now];
minnum[now << 1 | 1] += mark[now];
mark[now << 1 | 1] += mark[now];
mark[now] = 0;
}
if (l2 <= mid)
update(l1, mid, l2, r2, now << 1);
if (r2 > mid)
update(mid + 1, r1, l2, r2, now << 1 | 1);
minnum[now] = min(minnum[now << 1], minnum[now << 1 | 1]);
}
bool solve(double x){
memset(mark, 0, sizeof(mark));
for (int i = 1; i < maxn << 2; i++)
minnum[i] = inf;
for (int i = 1; i <= n; i++){
insert(1, n, i, 1, x);
update(1, n, Left[i] + 1, i, 1);
if (minnum[1] - x * (i + 1) < eps)
return true;
}
return false;
}
int main(){
int t;
scanf("%d", &t);
while (t--){
scanf("%d", &n);
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]);
Left[i] = vis[a[i]];
vis[a[i]] = i;
}
double l = 0, r = 1;
double ans = 0;
while (l - r < eps){
double mid = (l + r) / 2;
if (solve(mid)){
ans = mid;
r = mid - eps;
}
else
l = mid + eps;
}
printf("%.6lf\n", ans);
}
}