2017 Multi-University Training Contest - Team 4 hdu6070 Dirt Ratio
地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6070
题面:
Dirt Ratio
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1599 Accepted Submission(s): 740
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.思路:
分数规划的思想:二分答案,然后check。
check:dif(l,r)/(r-l+1)<=mid (dif(l,r)区间[l,r]的不同数个数)
这个形式很难在短时间内check,所以考虑等式变形。
变形成==》dif(l,r)+l*mid<=(r+1)*mid
在这种形式下可以通过枚举r,然后线段数维护左边的值。对于新加入的一个数,会在区间[pre[x],x]内贡献1,所以进行区间更新即可。
具体见代码:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define MP make_pair 6 #define PB push_back 7 typedef long long LL; 8 typedef pair<int,int> PII; 9 const double eps=1e-8; 10 const double pi=acos(-1.0); 11 const int K=6e4+7; 12 const int mod=1e9+7; 13 14 int n,a[K],pre[K],b[K]; 15 double v[4*K],lz[4*K]; 16 void push_down(int o) 17 { 18 v[o<<1]+=lz[o],v[o<<1|1]+=lz[o]; 19 lz[o<<1]+=lz[o],lz[o<<1|1]+=lz[o]; 20 lz[o]=0; 21 } 22 double update(int o,int l,int r,int pos,double x) 23 { 24 if(l==r) return v[o]=x; 25 int mid=l+r>>1; 26 push_down(o); 27 if(pos<=mid) update(o<<1,l,mid,pos,x); 28 else update(o<<1|1,mid+1,r,pos,x); 29 v[o]=min(v[o<<1],v[o<<1|1]); 30 } 31 double update2(int o,int l,int r,int nl,int nr,double x) 32 { 33 if(l==nl && r==nr) return v[o]+=x,lz[o]+=x; 34 int mid=l+r>>1; 35 push_down(o); 36 if(nr<=mid) update2(o<<1,l,mid,nl,nr,x); 37 else if(nl>mid) update2(o<<1|1,mid+1,r,nl,nr,x); 38 else update2(o<<1,l,mid,nl,mid,x),update2(o<<1|1,mid+1,r,mid+1,nr,x); 39 v[o]=min(v[o<<1],v[o<<1|1]); 40 } 41 bool check(double mid) 42 { 43 for(int i=1,mx=n*4;i<=mx;i++) v[i]=1e9,lz[i]=0; 44 for(int i=1;i<=n;i++) 45 { 46 update(1,1,n,i,i*mid); 47 update2(1,1,n,pre[i]+1,i,1.0); 48 if(v[1]<(i+1)*mid+eps) return 1; 49 } 50 return 0; 51 } 52 int main(void) 53 { 54 int t;cin>>t; 55 while(t--) 56 { 57 scanf("%d",&n); 58 memset(b,0,sizeof b); 59 for(int i=1;i<=n;i++) scanf("%d",a+i),pre[i]=b[a[i]],b[a[i]]=i; 60 double l=0,r=1; 61 for(int i=1;i<=14;i++) 62 { 63 double mid=(l+r)/2.0; 64 if(check(mid)) r=mid; 65 else l=mid; 66 } 67 printf("%.6f\n",l); 68 } 69 return 0; 70 }
作者:weeping
出处:www.cnblogs.com/weeping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。