hdu 6070 Dirt Ratio(分数规划)

题目链接:hdu 6070 Dirt Ratio

题意:

给你n个数,让你找一段区间[l,r],使得[l,r]中不同的数的个数size/(r-l+1)最小。

题解:

Claris官方题解:

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 3 using namespace std;
 4 
 5 const int N=6e4+7;
 6 int t,n,a[N],lazy[N*4],la[N];
 7 double T[N*4],eps=1e-4;
 8 
 9 void build(double v,int l=1,int r=n,int rt=1)
10 {
11     lazy[rt]=0;
12     if(l==r){T[rt]=l*v;return;}
13     int mid=l+r>>1;
14     build(v,l,mid,rt<<1),build(v,mid+1,r,rt<<1|1);
15     T[rt]=min(T[rt<<1],T[rt<<1|1]);
16 }
17 
18 void PD(int rt)
19 {
20     lazy[rt<<1]+=lazy[rt],lazy[rt<<1|1]+=lazy[rt];
21     T[rt<<1]+=lazy[rt],T[rt<<1|1]+=lazy[rt],lazy[rt]=0;
22 }
23 
24 void update(int L,int R,int v,int l=1,int r=n,int rt=1)
25 {
26     if(L<=l&&r<=R){lazy[rt]+=v,T[rt]+=v;return;}
27     int mid=l+r>>1;
28     if(lazy[rt])PD(rt);
29     if(L<=mid)update(L,R,v,l,mid,rt<<1);
30     if(R>mid)update(L,R,v,mid+1,r,rt<<1|1);
31     T[rt]=min(T[rt<<1],T[rt<<1|1]);
32 }
33 
34 double ask(int L,int R,int l=1,int r=n,int rt=1)
35 {
36     if(L<=l&&r<=R)return T[rt];
37     int mid=l+r>>1;
38     if(lazy[rt])PD(rt);double ans=1e12;
39     if(L<=mid)ans=min(ans,ask(L,R,l,mid,rt<<1));
40     if(R>mid)ans=min(ans,ask(L,R,mid+1,r,rt<<1|1));
41     return ans;
42 }
43 
44 int check(double mid)
45 {
46     build(mid),memset(la,0,sizeof(la));
47     F(r,1,n)
48     {
49         update(la[a[r]]+1,r,1);
50         la[a[r]]=r;
51         if(ask(1,r)<=mid*(r+1))return 1;
52     }
53     return 0;
54 }
55 
56 int main(){
57     scanf("%d",&t);
58     while(t--)
59     {
60         scanf("%d",&n);
61         F(i,1,n)scanf("%d",a+i);
62         double l=0,r=1,mid;
63         F(ic,1,15)
64         {
65             if(r-l<eps)break;
66             mid=(l+r)/2;
67             if(check(mid))r=mid;else l=mid;
68         }
69         printf("%f
",mid);
70     }
71     return 0;
72 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/7291320.html