二分答案mid,检验是否存在一个区间满足size(l,r)/(r-l+1) ≤mid,也就是size(l,r)+mid*l≤mid*(r+1)。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int maxn=6e4+10;
int tt,n,a[maxn],pos[maxn],add[maxn<<2];
double L,R,MID,t,v[maxn<<2];
void PushUp(int rt){
v[rt]=min(v[rt<<1],v[rt<<1|1]);
}
void PushDown(int rt){
if(add[rt]){
add[rt<<1]+=add[rt],v[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt],v[rt<<1|1]+=add[rt];
add[rt]=0;
}
}
void build(int l,int r,int rt){
v[rt]=MID*l,add[rt]=0;
if(l==r) return;
int mid=(l+r)/2;
build(lson),build(rson);
}
void updata(int l,int r,int rt,int LL,int RR){
//printf("%d %d %d %d\n",l,r,LL,RR);
if(LL<=l&&r<=RR){
add[rt]++,v[rt]++;
return;
}
PushDown(rt);
int mid=(l+r)/2;
if(LL<=mid) updata(lson,LL,RR);
if(RR>mid) updata(rson,LL,RR);
PushUp(rt);
}
void query(int l,int r,int rt,int RR){
if(r<=RR){
t=min(t,v[rt]);
return;
}
PushDown(rt);
int mid=(l+r)/2;
query(lson,RR);
if(RR>mid) query(rson,RR);
}
int main(){
scanf("%d",&tt);
while(tt--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
L=0,R=1;
for(int c=0;c<20;c++){
MID=(L+R)/2;
build(1,n,1);
int i;
for(i=1;i<=n;i++) pos[i]=0;
for(i=1;i<=n;i++){
updata(1,n,1,pos[a[i]]+1,i);
t=1e9;
query(1,n,1,i);
if(t-MID*(i+1)<=0) break;
pos[a[i]]=i;
}
if(i>n) L=MID;
else R=MID;
}
printf("%.10f\n",(L+R)/2);
}
}