hdu 6070(二分 线段树区间维护)

二分mid

size(l, r) / (r - l + 1) <= mid -> size(l, r) <= mid * (r - l + 1) -> size(l, r) + mid * l <= mid * (r + 1)

暴力枚举r线段树维护左边的式子

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
const int maxn = 60005;
const double EPS = 1e-7;
double tree[maxn * 4];
int lazy[maxn * 4], a[maxn], vis[maxn], pre[maxn];
void build(int l, int r, int o, double t)
{
    if(l == r)
    {
        tree[o] = t * l;
        lazy[o] = 0;
    }
    else
    {
        int mid = (l + r) >> 1;
        build(l, mid, o * 2, t);
        build(mid + 1, r, o * 2 + 1, t);
        lazy[o] = 0;
        tree[o] = min(tree[o * 2], tree[o * 2 + 1]);
    }
}
int x1, x2;
void pushdown(int o)
{
    tree[o * 2] += lazy[o];
    lazy[o * 2] += lazy[o];
    tree[o * 2 + 1] += lazy[o];
    lazy[o * 2 + 1] += lazy[o];
    lazy[o] = 0;
}
void update(int l, int r, int o)
{
    if(x1 <= l && r <= x2)
    {
        ++lazy[o];
        tree[o] += 1;
    }
    else
    {
        pushdown(o);
        int mid = (l + r) >> 1;
        if(x1 <= mid)
            update(l, mid, o * 2);
        if(x2 > mid)
            update(mid + 1, r, o * 2 + 1);
        tree[o] = min(tree[o * 2], tree[o * 2 + 1]);
    }
}
double query(int l, int r, int o)
{
    if(x1 <= l && r <= x2)
    {
        return tree[o];
    }
    else
    {
        pushdown(o);
        int mid = (l + r) >> 1;
        double ret;
        if(x2 <= mid)
            ret = query(l, mid, o * 2);
        else if(x1 > mid)
            ret = query(mid + 1, r, o * 2 + 1);
        else
            ret = min(query(l, mid, o * 2), query(mid + 1, r, o * 2 + 1));
        tree[o] = min(tree[o * 2], tree[o * 2 + 1]);
        return ret;
    }
}
void print(int l, int r, int o)
{
    if(l == r)
    {
        cout << "l == " << l << " r == " << r << " o == " << o << endl;
        cout << "tree == " << tree[o] << " lazy == " << lazy[o] << endl;
        return ;
    }
    else
    {
        int mid = (l + r) >> 1;
        print(l, mid, o * 2);
        print(mid + 1, r, o * 2 + 1);
        cout << "l == " << l << " r == " << r << " o == " << o << endl;
        cout << "tree == " << tree[o] << " lazy == " << lazy[o] << endl;

    }
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        memset(vis, 0, sizeof(vis));
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= n; ++i)
        {
            pre[i] = vis[a[i]];
            vis[a[i]] = i;
        }
        double l = 0, r = 1;
        while(fabs(r - l) > EPS)
        {
            double mid = (l + r) / 2;
            int flag = 0;
            build(1, n, 1, mid);
            for(int i = 1; i <= n; ++i)
            {
                x1 = pre[i] + 1, x2 = i;
                update(1, n, 1);
                x1 = 1, x2 = i;
                double tmp = query(1, n, 1);
//                for(int j = 1; j <= n; ++j)
//                {
//                    x1 = x2 = j;
//                    cout << query(1, n, 1) << " ";
//                }
//                cout << endl;
//                cout << "i == " << i << endl;
//                print(1, n, 1);
//                if(mid == 0.25)
//                {
//                    cout << "tmp == " << tmp << endl;
//                }
                if(tmp < mid * (i + 1))
                {
//                    cout << "tmp == " << tmp << endl;
//                    cout << "****" << endl;
//                    cout << "i == " << i << " tmp == " << tmp << " mid == " << mid << endl;
                    flag = 1;
                    break;
                }
            }
            if(flag)
            {
                r = mid;
            }
            else
            {
                l = mid;
            }
        }
        printf("%.6f\n", l);
    }
}
View Code

 

posted @ 2017-08-14 15:50  兰朵露可  阅读(119)  评论(0)    收藏  举报