第四場 hdu 6070 Dirt Ratio (線段樹+二分)

http://acm.hdu.edu.cn/showproblem.php?pid=6070php

 

題目大意:給出的序列上的數表明顏色,求子序列中不一樣數字的個數X與子序列長度Y中,X/Y的最小值html

 

解題思路:思路和官方給的想法同樣ios

值得注意的是線段樹的節點中儲存的是 size(l,r)+mid×l ,在建樹時 mid×l 做爲樹節點的初始值,而後不斷更新當前顏色對於 前一個相同顏色的位置+1 到 當前位置 的節點值+1,而後詢問 1 到 當前位置的最小值 是否小於mid*(i+1)。c++

雖然最後要打印小數點後九位可是精度只要達到小數點後五位就能夠了。ui

 

AC代碼:4056MSspa

 1 #include <iostream>
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 const int maxn=60100;
 5 const double eps=1e-5;
 6 int a[maxn],flag[maxn];
 7 double val[maxn<<2],lazy[maxn<<2];
 8 int t,n;
 9 void push_up(int k)
10 {
11     val[k]=min(val[k*2],val[k*2+1]);
12 }
13 void push_down(int k)
14 {
15     if(lazy[k])
16     {
17         lazy[k*2]+=lazy[k];
18         lazy[k*2+1]+=lazy[k];
19         val[k*2]+=lazy[k];
20         val[k*2+1]+=lazy[k];
21         lazy[k]=0;
22     }
23 }
24 void build(double mid,int l,int r,int k)
25 {
26     lazy[k]=0;
27     if(l==r)
28     {
29         val[k]=l*mid;
30         return ;
31     }
32     int midd=(l+r)/2;
33     build(mid,l,midd,k*2);
34     build(mid,midd+1,r,k*2+1);
35     push_up(k);
36 }
37 void init(int L,int R,int l,int r,int k)
38 {
39     if(L<=l&&r<=R)
40     {
41         val[k]=val[k]+1;
42         lazy[k]+=1;
43         return ;
44     }
45     push_down(k);
46     int mid=(l+r)/2;
47     if(L<=mid) init(L,R,l,mid,k*2);
48     if(R>mid) init(L,R,mid+1,r,k*2+1);
49     push_up(k);
50 }
51 double query(int L,int R,int l,int r,int k)
52 {
53     if(L<=l&&r<=R)
54     {
55         return val[k];
56     }
57     push_down(k);
58     int mid=(l+r)/2;
59     double ans=1e5;
60     if(L<=mid) ans=query(L,R,l,mid,k*2);
61     if(R>mid) ans=min(ans,query(L,R,mid+1,r,k*2+1));
62     push_up(k);
63     return ans;
64 }
65 bool solve(double mid)
66 {
67     memset(flag,0,sizeof(flag));
68     build(mid,1,n,1);
69     for(int i=1;i<=n;i++)
70     {
71         init(flag[a[i]]+1,i,1,n,1);
72         flag[a[i]]=i;
73         if(query(1,i,1,n,1)<=mid*(i+1)) return true;
74     }
75     return false;
76 }
77 int main()
78 {
79 
80     scanf("%d",&t);
81     //freopen("data.txt","w",stdout);
82     while(t--)
83     {
84         scanf("%d",&n);
85         for(int i=1;i<=n;i++)
86         scanf("%d",&a[i]);
87         double l=0,r=1,mid,ans;
88         while(r-l>eps)
89         {
90             mid=(l+r)/2;
91             if(solve(mid))
92             r=(ans=mid)-eps;
93             else
94             l=mid+eps;
95         }
96         printf("%.9lf\n",ans);
97     }
98     return 0;
99 }
相關文章
相關標籤/搜索