zoukankan      html  css  js  c++  java
  • hdu6070

    hdu6070

    题意

    给出 (n) 个数, (frac{x}{y}) 表示某个区间不同数的个数除以区间的长度,求 (frac{x}{y}) 最小值。

    分析

    (size(l, r)) 表示 ([l, r]) 这个区间内不同数的个数,那么求得就是 (frac{size(l, r)}{r - l + 1}) 的最小值。
    二分答案 (mid) ,式子转化成 (size(l, r) + mid imes l leq mid imes (r + 1))
    枚举右端点 (r),线段树存的是从 (l) 到 当前枚举到的 (r)(size(l, r) + mid imes l) ,如果存在最小值满足小于等于 (mid imes (r + 1)) ,说明这个 (mid) 可以取到,更新 (mid)

    新姿势:线段树内每个点的信息是动态的,和枚举到的 (r) 有关,通过区间更新就可以很方便的计算 (size(l, r)) 的值。

    (last[a[i]]) 表示 (a[i]) 这个数上一次出现的位置,那么每次我们只需要区间更新 ([last[a[i]] + 1, i]) 就好了。

    code

    #include<bits/stdc++.h>
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    using namespace std;
    const int MAXN = 6e4 + 10;
    int a[MAXN];
    int last[MAXN];
    double s[MAXN << 2];
    double lazy[MAXN << 2];
    void pushDown(int rt) {
        if(lazy[rt] > 0) {
            s[rt << 1] += lazy[rt];
            s[rt << 1 | 1] += lazy[rt];
            lazy[rt << 1] += lazy[rt];
            lazy[rt << 1 | 1] += lazy[rt];
            lazy[rt] = 0;
        }
    }
    void pushUp(int rt) {
        s[rt] = min(s[rt << 1], s[rt << 1 | 1]);
    }
    void update(int L, int R, double c, int l, int r, int rt) {
        if(L <= l && r <= R) {
            lazy[rt] += c;
            s[rt] += c;
            return;
        }
        int m = (l + r) / 2;
        pushDown(rt);
        if(L <= m) update(L, R, c, lson);
        if(R > m) update(L, R, c, rson);
        pushUp(rt);
    }
    double query(int L, int R, int l, int r, int rt) {
        if(L <= l && r <= R) {
            return s[rt];
        }
        int m = (l + r) / 2;
        pushDown(rt);
        double res = 1e12;
        if(L <= m) res = query(L, R, lson);
        if(R > m) res = min(res, query(L, R, rson));
        pushUp(rt);
        return res;
    }
    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.0, mid;
            while(r - l > 1e-5) {
                mid = (l + r) / 2.0;
                memset(s, 0, sizeof s);
                memset(lazy, 0, sizeof lazy);
                memset(last, 0, sizeof last);
                int flg = 0;
                for(int i = 1; i <= n; i++) {
                    update(last[a[i]] + 1, i, 1, 1, n, 1);
                    update(i, i, mid * i, 1, n, 1);
                    if(query(1, i, 1, n, 1) <= mid * (i + 1)) {
                        flg = 1;
                        break;
                    }
                    last[a[i]] = i;
                }
                if(flg) r = mid;
                else l = mid;
            }
            printf("%.6f
    ", mid);
        }
        return 0;
    }
    
  • 相关阅读:
    python---1
    20190802—list、range、extend函数
    20190802—def定义函数
    20190802—import函数调用
    如何在EXCEL中将多个单元格内容合并到一个单元格中
    20190619—return函数的用法
    20190618—位置参数、默认参数、不定长参数
    excel 怎么计算单元格个数
    20190616——and和or使用方法、python运算符总结、python数据类型
    20190616——enumerate的用法
  • 原文地址:https://www.cnblogs.com/ftae/p/7291765.html
Copyright © 2011-2022 走看看