多校联合的题,之前竟然没有补,今天补上。
这个题的区间具有不可重叠性。
用线段树存放的是一个起点固定的 (不同数字数加l*k);
code:
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<cmath>
using namespace std;
const int maxn=60010;
const double eps=1e-5;
struct node
{
int l,r;
double add;
double mn;
}tree[maxn<<2];
void pushup(int index)
{
tree[index].mn=min(tree[index<<1].mn,tree[index<<1|1].mn);
}
void pushdown(int index)
{
tree[index<<1].mn+=tree[index].add;
tree[index<<1|1].mn+=tree[index].add;
tree[index<<1].add += tree[index].add;
tree[index<<1|1].add += tree[index].add;
tree[index].add=0.0;
}
void build(int l,int r,int index,double k)
{
tree[index].l=l;
tree[index].r=r;
tree[index].add=0.0;
if(l==r)
{
tree[index].mn=l*1.00*k;
//printf("%d %f\n",l,tree[index].mn);
return ;
}
int mid=(l+r)>>1;
build(l,mid,index<<1,k);
build(mid+1,r,index<<1|1,k);
pushup(index);
}
void update(int l,int r,int index,double val)
{
if(l<=tree[index].l&&tree[index].r<=r)
{
tree[index].mn+=val;
tree[index].add+=val;
return ;
}
pushdown(index);
int mid=(tree[index].l+tree[index].r)>>1;
if(l<=mid)
{
update(l,r,index<<1,val);
}
if(r>mid)
{
update(l,r,(index<<1|1),val);
}
pushup(index);
}
double query(int l,int r,int index)
{
if(l<=tree[index].l&&tree[index].r<=r)
{
return tree[index].mn;
}
pushdown(index);
int mid=(tree[index].l+tree[index].r)>>1;
double Min=1210000.0;
if(l<=mid)
{
Min=min(query(l,r,index<<1),Min);
}
if(r>mid)
{
Min=min(query(l,r,index<<1|1),Min);
}
//cout<<Min<<endl;
return Min;
}
int pre[maxn];
int a[maxn];
int main()
{
int _case;
scanf("%d",&_case);
while(_case--)
{
int n;
scanf("%d",&n);
memset(pre,0,sizeof(pre));
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
}
double left=0.0;
double right=1.00;
while(right-left>eps)
{
memset(pre,0,sizeof(pre));
double mid=(right+left)/2.00;
build(1,n,1,mid);
bool flag=false;
for(int i=1;i<=n;i++)
{
int R=pre[a[i]];
/*printf("%d %d\n",R+1,i);*/
update(R+1,i,1,1.00);
pre[a[i]]=i;
/*for(int j=1;j<=i;j++)
{
cout<<j<<" "<< query(j,j,1)<<endl;
}*/
if(query(1,i,1)<=mid+mid*(double)i)
{
//printf("i=%d you=%f\n",i,mid+mid*(double)i);
flag=true;
break;
}
}
if(flag)
{
right=mid;
}
else
{
left=mid;
}
}
printf("%.10f\n",(left+right)/2.00);
}
return 0;
}