Dirt Ratio
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 335 Accepted Submission(s): 105
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.
![](http://acm.hdu.edu.cn/data/images/C762-1004-1.jpg)
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''.
![](http://acm.hdu.edu.cn/data/images/C762-1004-1.jpg)
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
题意:给你一个长度为n的区间 X=区间不同数的个数 Y=区间长度 求子区间X/Y的最小值
题解:二分答案mid check X/Y<=mid
X/Y=X/(r-L+1)<=mid
=> X+L*mid<=(r+1)*mid
建树初始每个点的maxn为L*mid
从左向右遍历右边界 遍历到r 更新(last[r]+1,r) 值增加1 last[r]表示a[r]相同值的上一个位置
r之前的每个结点L存的是L到r不同数的个数X+L*mid (这些便是不等式的左边)取最小值 与 (r+1)*mid 比较
1 #pragma comment(linker, "/STACK:102400000,102400000") 2 #include <bits/stdc++.h> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <iostream> 6 #include <cstdlib> 7 #include <cstring> 8 #include <algorithm> 9 #include <cmath> 10 #include <cctype> 11 #include <map> 12 #include <set> 13 #include <queue> 14 #include <bitset> 15 #include <string> 16 #include <complex> 17 #define LL long long 18 #define mod 1000000007 19 using namespace std; 20 int t; 21 int n; 22 int a[65003]; 23 int last[65003]; 24 map<int,int> mp; 25 struct node 26 { 27 int l,r; 28 double maxn; 29 int add; 30 } tree[500005]; 31 void buildtree(int root ,int left,int right,double zz) 32 { 33 tree[root].l=left; 34 tree[root].r=right; 35 tree[root].add=0; 36 if(left==right) 37 { 38 tree[root].maxn=left*zz; 39 return ; 40 } 41 int mid=(left+right)>>1; 42 buildtree(root<<1,left,mid,zz); 43 buildtree(root<<1|1,mid+1,right,zz); 44 tree[root].maxn=min(tree[root<<1].maxn,tree[root<<1|1].maxn); 45 } 46 void pushdown(int root) 47 { 48 if(tree[root].add==0) return ; 49 tree[root<<1].add+=tree[root].add; 50 tree[root<<1|1].add+=tree[root].add; 51 tree[root<<1].maxn+=tree[root].add; 52 tree[root<<1|1].maxn+=tree[root].add; 53 tree[root].add=0; 54 } 55 void update(int root,int left,int right,int c) 56 { 57 if(tree[root].l==left&&tree[root].r==right) 58 { 59 tree[root].add+=c; 60 tree[root].maxn+=c; 61 return ; 62 } 63 pushdown(root); 64 int mid=(tree[root].l+tree[root].r)>>1; 65 if(right<=mid) 66 { 67 update(root<<1,left,right,c); 68 } 69 else 70 { 71 if(left>mid) 72 update(root<<1|1,left,right,c); 73 else 74 { 75 update(root<<1,left,mid,c); 76 update(root<<1|1,mid+1,right,c); 77 78 } 79 } 80 tree[root].maxn=min(tree[root<<1].maxn,tree[root<<1|1].maxn); 81 } 82 double query(int root,int left,int right) 83 { 84 if(left>right) 85 return 0; 86 if(tree[root].l==left&&tree[root].r==right) 87 { 88 return tree[root].maxn; 89 } 90 pushdown(root); 91 int mid=(tree[root].l+tree[root].r)>>1; 92 if(right<=mid) 93 return query(root<<1,left,right); 94 else 95 { 96 if(left>mid) 97 return query(root<<1|1,left,right); 98 else 99 return min(query(root<<1,left,mid),query(root<<1|1,mid+1,right)); 100 } 101 } 102 bool check (double x) 103 { 104 buildtree(1,1,n,x); 105 for(int i=1; i<=n; i++) 106 { 107 update(1,last[i]+1,i,1); 108 double zha=(double)query(1,1,i); 109 if(zha<=(i+1)*x) 110 return true; 111 } 112 return false; 113 } 114 int main() 115 { 116 scanf("%d",&t); 117 for(int kk=1;kk<=t;kk++){ 118 scanf("%d",&n); 119 mp.clear(); 120 for(int i=1; i<=n; i++){ 121 scanf("%d",&a[i]); 122 last[i]=mp[a[i]]; 123 mp[a[i]]=i; 124 } 125 double l=0,r=1.0,mid,ans; 126 while(abs(l-r)>=0.00001) 127 { 128 mid=(l+r)/2; 129 if(check(mid)){ 130 ans=mid; 131 r=mid; 132 } 133 else 134 l=mid; 135 } 136 printf("%f\n",ans); 137 } 138 return 0; 139 }