/*
hdu6070 

二分答案 mid,检验是否存在一个区间满足
size(l,r)
r−l+1
≤ mid,也就是 size(l, r) + mid × l ≤
mid × (r + 1)。
从左往右枚举每个位置作为 r,当 r 变化为 r + 1 时,对 size 的影响是一段区间加 1,线
段树维护区间最小值即可。
时间复杂度 O(n log n log w)。

照抄自Claris题解
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
#define ll long long 
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define frr(i,a,b) for(int i=a;i>=b;i--)
#define ms(a,b) memset(a,b,sizeof(a))
#define scfd(a) scanf("%d",a)
#define scflf(a) scanf("%lf",a)
#define scfs(a) scanf("%s",a)
#define ptfd(a) printf("%d\n",a)
#define ptfs(a) printf("%s\n",a)
#define showd(a,b) printf(a"=%d\n",b)
#define showlf(a,b) printf(a"=%lf\n",b)
#define shows(a,b) printf(a"=%s\n",b)
#define mmcp(a,b) memcpy(a,b,sizeof(b))
const int MAXN=60005;
int cases,n;
int pre[MAXN];
double v[MAXN];
double stn[MAXN*4];
double laz[MAXN*4];
void build(int now,int l,int r,double t){
	if(l==r-1){
		stn[now]=t*(double)l;
		return;
	}
	int mid=(l+r)/2;
	build(now<<1,l,mid,t);
	build((now<<1)+1,mid,r,t);
	stn[now]=min(stn[now<<1],stn[(now<<1)+1]);
}
void push_down(int now){
	laz[now<<1]+=laz[now];
	laz[(now<<1)+1]+=laz[now];
	stn[now<<1]+=laz[now];
	stn[(now<<1)+1]+=laz[now];
	laz[now]=0;
}
double find(int now,int l,int r,int kl,int kr){
	if(kl<=l&&kr>=r)
		return stn[now];
	push_down(now);
	double ans=214748363;
	int mid=(l+r)/2;
	if(kl<mid)
		ans=min(ans,find(now<<1,l,mid,kl,kr));
	if(kr>mid)
		ans=min(ans,find((now<<1)+1,mid,r,kl,kr));
	return ans;
}
void update(int now,int l,int r,int kl,int kr){
	if(kl<=l&&kr>=r){
		laz[now]+=1.0;
		stn[now]+=1.0;
		return;
	}
	push_down(now);
	int mid=(l+r)/2;
	if(kl<mid)
		update(now<<1,l,mid,kl,kr);
	if(kr>mid)
		update((now<<1)+1,mid,r,kl,kr);
	stn[now]=min(stn[now<<1],stn[(now<<1)+1]);
}
int main(){
	// freopen("1004.in","r",stdin);
	// freopen("i004.out","w",stdout);
	scfd(&cases);
	while(cases--){
		scfd(&n);
		fr(i,1,n)
			scflf(&v[i]);
		double l=0,r=1.0;

		int times=25;
		while(times--){
			double mid=(l+r)/2;
			build(1,1,n+1,mid);
			ms(pre,0);
			ms(laz,0);
			bool suc=false;
			fr(i,1,n){
				update(1,1,n+1,pre[(int)v[i]]+1,i+1);
				double t=find(1,1,n+1,1,i+1);
				if(t-(i+1)*mid<=0){
					suc=true;
					break;
				}
				pre[(int)v[i]]=i;
			}
			if(suc)
				r=mid;
			else
				l=mid;
		}
		printf("%.10lf\n",(r+l)/2);
	}
	return 0;
}
 posted on 2017-09-22 17:27  cylcy  阅读(74)  评论(0编辑  收藏  举报