1. 程式人生 > >第四場 hdu 6070 Dirt Ratio (線段樹+二分)

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

math sizeof i++ 樹節點 size iostream col 個數 ext

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

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

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

技術分享

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

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

AC代碼:4056MS

 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 }

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