zoukankan      html  css  js  c++  java
  • HDU 6070

    比赛时会错题意+不知道怎么线段树维护分数- -

    思路来自题解

    /*
    HDU 6070 - Dirt Ratio [ 二分,线段树 ]  |  2017 Multi-University Training Contest 4
    题意:
    	给出 a[N];
    	设 size(l,r)为区间(l,r)不同数字的个数,求 size(l,r)/(r-l+1) 的最小值
    	限制: N <= 6e5, a[i] <= 6e5
    分析:
    	二分答案 mid
    	则判定条件为是否存在 size(l,r)/(r-l+1) <= mid 
    	变换一下:  size(l,r) + mid*l <= mid * (r+1)
    	将左式存入线段树中,枚举 r,对某段 l 进行更新(last[a[r]+1] 到 r),更新操作为值+1
    		再对每个 r 判断一下上式是否成立
    */
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 6e4+5;
    const double eps = 1e-5;
    const double INF = 1e18;
    namespace SegT {
        double val[N];
        double Min[N<<2]; int add[N<<2];
        void up(int x) {
            Min[x] = min(Min[x<<1], Min[x<<1|1]);
        }
        void down(int x) {
            if (add[x]) {
                add[x<<1] += add[x];
                Min[x<<1] += add[x];
                add[x<<1|1] += add[x];
                Min[x<<1|1] += add[x];
                add[x] = 0;
            }
        }
        void build(int l, int r, int x) {
            add[x] = 0;
            if (l == r) {
                Min[x] = val[l]; return;
            }
            int mid = (l+r) >> 1;
            build(l, mid, x<<1);
            build(mid+1, r, x<<1|1);
            up(x);
        }
        void change(int L, int R, int num, int l, int r, int x) {
            if (L <= l && r <= R) {
                add[x] += num;
                Min[x] += num;
                return;
            }
            down(x);
            int mid = (l+r) >> 1;
            if (L <= mid) change(L, R, num, l, mid, x<<1);
            if (mid < R) change(L, R, num, mid+1, r, x<<1|1);
            up(x);
        }
        double query(int L, int R, int l, int r, int x) {
            if (L <= l && r <= R) return Min[x];
            down(x);
            int mid = (l+r) >> 1;
            double res = INF;
            if (L <= mid) res = min(res, query(L, R, l, mid, x<<1));
            if (R > mid) res = min(res, query(L, R, mid+1, r, x<<1|1));
            return res;
        }
    }
    int t, n, a[N];
    int last[N];
    bool solve(double mid)
    {
        for (int i = 1; i <= n; i++)
            SegT::val[i] = i*mid;
        SegT::build(1, n, 1);
        memset(last, 0, sizeof(last));
        for (int i = 1; i <= n; i++)
        {
            SegT::change(last[a[i]]+1, i, 1, 1, n, 1);
            last[a[i]] = i;
            double res = SegT::query(1, i, 1, n, 1);
            if (res < (i+1)*mid - eps) return 1;
        }
        return 0;
    }
    double BinaryFind(double l, double r)
    {
        double mid;
        while ((r-l) > eps) {
            mid = (l+r) / 2;
            if (solve(mid)) r = mid;
            else l = mid;
        }
        return mid;
    }
    int main()
    {
        scanf("%d", &t);
        while (t--)
        {
            scanf("%d", &n);
            for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
            printf("%.9f
    ", BinaryFind(0, 1));
        }
    }
    

      

    我自倾杯,君且随意
  • 相关阅读:
    【LeetCode】1248. 统计「优美子数组」
    【LeetCode】200. 岛屿数量
    【LeetCode】53. 最大子序和
    【剑指Offer】面试题42. 连续子数组的最大和
    【剑指Offer】面试题57. 和为s的两个数字
    【LeetCode】55. 跳跃游戏
    【LeetCode】56. 合并区间
    简历HTML网页版
    关于新建Eclipse新建一个WEB项目后创建一个jsp文件头部报错问题?
    jquery选择器 看这个链接吧!2017.6.2
  • 原文地址:https://www.cnblogs.com/nicetomeetu/p/7282626.html
Copyright © 2011-2022 走看看