Dirt RatioTime Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 621 Accepted Submission(s): 239 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''.
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.
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
Sample Output
|
二分答案,(size(l,r))/(r-l+1)<=mid;,为了维护最小值,一定有一个值是变量,一个是定值,因为表达式中只有l和r,所以更改表达式为size(l,r)+l*mid<=mid*(r+1);
从左往右枚举右端点,因为前面的所有区间都已经知道最小值了,所以更新后就是前面所有左端点到当前端点的最小值,题目做的不多根本想不到这样变换
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include <bits/stdc++.h>
using namespace std;
const int N = 60150+7;
typedef long long LL;
const LL mod = 1e9+7;
int pre[N], lazy[N<<2], a[N];
double sum[N<<2];
int n, id;
void build(int l,int r,int rt,double mid1)
{
lazy[rt]=0;
if(l==r)
{
sum[rt]=mid1*l;
return ;
}
int mid=(l+r)/2;
build(l,mid,rt*2,mid1);
build(mid+1,r,rt*2+1,mid1);
sum[rt]=min(sum[rt*2],sum[rt*2+1]);
return ;
}
void pushdown(int rt)
{
if(lazy[rt])
{
lazy[rt*2]+=lazy[rt],lazy[rt*2+1]+=lazy[rt];
sum[rt*2]+=lazy[rt],sum[rt*2+1]+=lazy[rt];
lazy[rt]=0;
}
return ;
}
void update(int L,int R,int l,int r,int rt,int c)
{
if(l>=L&&r<=R)
{
sum[rt]+=c,lazy[rt]+=c;
return ;
}
pushdown(rt);
int mid=(l+r)/2;
if(L<=mid) update(L,R,l,mid,rt*2,c);
if(R>mid) update(L,R,mid+1,r,rt*2+1,c);
sum[rt]=min(sum[rt*2],sum[rt*2+1]);
return ;
}
double query(int l,int r,int rt,int L,int R)
{
if(l>=L&&r<=R) return sum[rt];
pushdown(rt);
int mid=(l+r)/2;
double ans=0x3f3f3f3f;
if(L<=mid) ans=min(ans,query(l,mid,rt*2,L,R));
if(R>mid) ans=min(ans,query(mid+1,r,rt*2+1,L,R));
return ans;
}
double judge(double mid)
{
build(1,n,1,mid);
memset(pre,0,sizeof(pre));
for(int i=1; i<=n; i++)
{
update(pre[a[i]]+1,i,1,n,1,1);
double x=query(1,n,1,1,i);
if(x<=mid*(i+1)) return 1;
pre[a[i]]=i;
}
return 0;
}
int main()
{
//cout<<(N<<2)<<endl;
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
memset(pre,0,sizeof(pre));
for(int i=1; i<=n; i++) scanf("%d", &a[i]);
double l=0, r=1, ans;
for(int i=0; i<=20; i++)
{
double mid=(l+r)/2;
if(judge(mid)) r=mid, ans=mid;
else l=mid;
}
printf("%.10f\n",ans);
}
return 0;
}