官方题解:
这个维护的最小值即 size(L, R)+Mid*L
代码:
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define CLR(A, X) memset(A, X, sizeof(A))
#define lson o<<1
#define rson o<<1|1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const double eps = 1e-10;
int dcmp(double x){if(fabs(x)<eps) return 0; return x<0?-1:1;}
const int INF = 0x3f3f3f3f;
const LL MOD = 21092013;
const int N = 6e4+5;
int a[N], pre[N], ql, qr;
double _min;
struct IntervalTree {
double minv[4*N], Mid;
int addv[4*N];
void maintain(int o, int L, int R) {
if(R > L) minv[o] = min(minv[lson], minv[rson]);
else minv[o] = Mid*L;
if(addv[o]) minv[o] += addv[o];
}
void pushdown(int o) {
addv[lson] += addv[o];
addv[rson] += addv[o];
addv[o] = 0;
}
void update(int o, int L, int R) {
if(ql<=L && qr>=R) addv[o]++;
else {
pushdown(o);
int M = (L+R)>>1;
if(ql <= M) update(lson, L, M); else maintain(lson, L, M);
if(qr > M) update(rson, M+1, R); else maintain(rson, M+1, R);
}
maintain(o, L, R);
}
void query(int o, int L, int R, int add) {
if(ql<=L && qr>=R) {
_min = min(_min, minv[o]+add);
}
else {
int M = (L+R)>>1;
if(ql <= M) query(lson, L, M, add+addv[o]);
if(qr > M) query(rson, M+1, R, add+addv[o]);
}
}
void build(int o, int L, int R) {
if(L == R) {
minv[o] = Mid*L;
addv[o] = 0;
return;
}
int M = (L+R)>>1;
build(lson, L, M);
build(rson, M+1, R);
minv[o] = min(minv[lson], minv[rson]);
addv[o] = 0;
}
}A;
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
double L = 0, R = 1;
for(int i = 0; i < 20; i++) {
double M = A.Mid = (L+R)/2.0;
A.build(1, 1, n);
for(int j = 1; j <= n; j++) pre[a[j]] = 0;
bool flag = 0;
for(int ri = 1; ri <= n; ri++) {
ql = pre[a[ri]]+1, qr = ri;
A.update(1, 1, n);
pre[a[ri]] = ri;
_min = 1e9;
ql = 1, qr = ri;
A.query(1, 1, n, 0);
if(_min <= M*(ri+1)) { flag = 1; break; }
}
if(flag) R = M;
else L = M;
}
printf("%.10f\n", L);
}
return 0;
}