题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070
题意:给个数列,问取一个子序列,子序列里面如果出现相同的数,计数器cnt +1,最后求所有的子序列中cnt/序列长度的最小值。
解法:SB题,我真的SBBBBBBBBBBBBBBBBBBB。。。被虐记。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
struct FastIO
{
static const int S = 1310720;
int wpos;
char wbuf[S];
FastIO() : wpos(0) {}
inline int xchar()
{
static char buf[S];
static int len = 0, pos = 0;
if (pos == len)
pos = 0, len = fread(buf, 1, S, stdin);
if (pos == len) return -1;
return buf[pos ++];
}
inline int xuint()
{
int c = xchar(), x = 0;
while (c <= 32) c = xchar();
for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
return x;
}
inline int xint()
{
int s = 1, c = xchar(), x = 0;
while (c <= 32) c = xchar();
if (c == '-') s = -1, c = xchar();
for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
return x * s;
}
inline void xstring(char *s)
{
int c = xchar();
while (c <= 32) c = xchar();
for (; c > 32; c = xchar()) * s++ = c;
*s = 0;
}
inline void wchar(int x)
{
if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
wbuf[wpos ++] = x;
}
inline void wint(LL x)
{
if (x < 0) wchar('-'), x = -x;
char s[24];
int n = 0;
while (x || !n) s[n ++] = '0' + x % 10, x /= 10;
while (n--) wchar(s[n]);
}
inline void wstring(const char *s)
{
while (*s) wchar(*s++);
}
~FastIO()
{
if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
}
} io;
const double eps = 1e-6;
const int maxn = 60010;
int n, last[maxn],a[maxn];
struct node{
int l,r;
double val,add;
}tree[maxn<<2];
void pushup(int rt){
tree[rt].val=min(tree[rt*2].val,tree[rt*2+1].val);
}
void pushdown(int rt){
if(tree[rt].add){
tree[rt<<1].val=tree[rt<<1].val+tree[rt].add;
tree[rt<<1|1].val=tree[rt<<1|1].val+tree[rt].add;
tree[rt<<1].add+=tree[rt].add;
tree[rt<<1|1].add+=tree[rt].add;
tree[rt].add=0;
}
}
void build(int l,int r,int rt, double x){
tree[rt].l=l,tree[rt].r=r,tree[rt].add=0;
if(l==r){
tree[rt].val=1.0*x*l;
return;
}
int mid=(l+r)/2;
build(l,mid,rt*2,x);
build(mid+1,r,rt*2+1,x);
pushup(rt);
}
void update(int L,int R,double val, int rt){
if(L<=tree[rt].l&&tree[rt].r<=R){
tree[rt].val+=val;
tree[rt].add+=val;
return;
}
pushdown(rt);
int mid=(tree[rt].l+tree[rt].r)/2;
if(R<=mid) update(L,R,val,rt*2);
else if(L>mid) update(L,R,val,rt*2+1);
else{
update(L,mid,val,rt*2);
update(mid+1,R,val,rt*2+1);
}
pushup(rt);
}
double query(int L, int R, int rt){
if(L<=tree[rt].l&&tree[rt].r<=R){
return tree[rt].val;
}
pushdown(rt);
int mid=(tree[rt].l+tree[rt].r)/2;
if(R<=mid) return query(L,R,rt*2);
else if(L>mid) return query(L,R,rt*2+1);
else{
return min(query(L,mid,rt*2), query(mid+1,R,rt*2+1));
}
}
bool check(double mid)
{
for(int i=1; i<=n; i++) last[i]=0;
build(1,n,1,mid);
for(int i=1; i<=n; i++){
update(last[a[i]]+1,i,1.0,1);
double mi = query(1,i,1);
if((mi-mid*(i+1))<=0) return true;
last[a[i]]=i;
}
return false;
}
int main()
{
int T;
T = io.xint();
while(T--){
n = io.xint();
for(int i=1; i<=n; i++){
a[i] = io.xint();
}
double l = 0, r = 1.0;
for(int i=0; i<20; i++){
double mid = (l+r)/2.0;
if(check(mid)) r=mid;
else l=mid;
}
printf("%.10f\n", (l+r)/2.0);
}
return 0;
}