Dirt Ratio
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
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 Xproblems 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.5000000000
Hint
For every problem, you can assume its final submission is accepted.
Source
官方题解:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cmath> #include<string> #include<queue> #include<algorithm> #include<stack> #include<cstring> #include<vector> #include<list> #include<set> #include<map> #include<stdlib.h> #include<time.h> #include<bits/stdc++.h> using namespace std; #define LL long long #define pi (4*atan(1.0)) #define bug(x) cout<<"bug"<<x<<endl; #define eps 1e-4 const int N=6e4+10,M=1e6+10,inf=2147483647; const LL INF=1e18+10,mod=998244353; struct is { double minn[N<<2]; int lazy[N<<2]; void pushdown(int pos) { if(lazy[pos]) { minn[pos<<1]+=lazy[pos]; minn[pos<<1|1]+=lazy[pos]; lazy[pos<<1|1]+=lazy[pos]; lazy[pos<<1]+=lazy[pos]; lazy[pos]=0; } } void build(int l,int r,int pos,double m) { lazy[pos]=0; if(l==r) { minn[pos]=m*l; return; } int mid=(l+r)>>1; build(l,mid,pos<<1,m); build(mid+1,r,pos<<1|1,m); minn[pos]=min(minn[pos<<1],minn[pos<<1|1]); } void update(int L,int R,int z,int l,int r,int pos) { if(L<=l&&r<=R) { minn[pos]+=z; lazy[pos]+=z; return; } pushdown(pos); int mid=(l+r)>>1; if(L<=mid)update(L,R,z,l,mid,pos<<1); if(R>mid) update(L,R,z,mid+1,r,pos<<1|1); minn[pos]=min(minn[pos<<1],minn[pos<<1|1]); } double query(int L,int R,int l,int r,int pos) { if(L<=l&&r<=R)return minn[pos]; pushdown(pos); int mid=(l+r)>>1; double ans=99999999999; if(L<=mid)ans=min(ans,query(L,R,l,mid,pos<<1)); if(R>mid)ans=min(ans,query(L,R,mid+1,r,pos<<1|1)); return ans; } }tree; int n,pre[N],a[N]; int check(double x) { tree.build(1,n,1,x); memset(pre,0,sizeof(pre)); for(int i=1;i<=n;i++) { tree.update(pre[a[i]]+1,i,1,1,n,1); double p=tree.query(1,i,1,n,1); //cout<<i<<" "<<x<<" "<<p<<" "<<x*(i+1)<<endl; if(p<=x*(i+1))return 1; pre[a[i]]=i; } return 0; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); double s=0; double e=1,ans=-1; while(e-s>=eps) { double mid=(s+e)/2; if(check(mid)) { ans=mid; e=mid; } else s=mid; } printf("%f ",ans); } return 0; }