HDU 6070 Dirt Ratio

来源:互联网 发布:单片机时序图 编辑:程序博客网 时间:2024/06/08 07:00

官方题解:

这里写图片描述

这个维护的最小值即 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|1using 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;}