zoukankan      html  css  js  c++  java
  • hdu-6070(二分+线段树)

    ---------题目链接,戳这里------------

    题目意思:

    题目一通描述,弄得我完全懵逼。幸好讨论区,有题目意思。

    题目意思为:定义f(l,r) 为区间 [l,r] 的不同元素个数/区间长度。求最小的 f(l,r) 定义域:(0 < l leqslant r leqslant n)。题目意思,翻译转一下就是这么简单。

    思路:

    思路就是,官方题解给出的,二分+线段树;我们二分答案,mid。需要判断mid是否满足,假设我们定义 (sizeleft ( l,r ight ))为区间 [l,r] 的不同元素个数。那么就需要mid满足:(frac{sizeleft ( l,r ight )}{r-l+1}leq mid),按照题解进行变形式子可以得到:(size left ( l,r ight )+ mid imes l leq mid imes left ( r+1 ight )),我们可以对r进行从左到右的枚举。在每一次枚举中r就是一个常数。我们可以用线段树维护区间最小值,维护 (size left ( l,r ight )+ mid imes l) ,每次r+1,需要更新r,r这个区间,区间加mid×r。还有需要给r区间到之前出现a[r]位置的右边这个区间的size都会加1。所以两次更新,每次我们需要查询区间 [1,r] 的区间最小值。先写一个区间维护最小值的插线问线的线段树。进行二分 。over;二分的时候,如果满足条件说明mid还不是最小的所以把上限(r = mid),否则下限(l = mid)

    代码比较搓。还好能够AC (-.-)

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <cmath>
    #include <set>
    #include <map>
    #include <list>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <string>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    #include <stdlib.h>
    #include <time.h>
    using namespace std;
    typedef long long LL;
    const LL INF = 2e9 + 1e8;
    
    const double eps = 0.0000000001;
    void fre()
    {
        freopen("test.in", "r", stdin);
        freopen("test.out", "w", stdout);
    }
    #define MSET(a, b) memset(a, b, sizeof(a))
    const int MOD = 1e9 + 7;
    const int maxn = 1e6 + 100;
    
    int a[maxn], pre[maxn], pos[maxn];
    
    struct nyist
    {
        double tree[maxn], lazy[maxn];
        void init()
        {
            MSET(tree, 0);
            MSET(lazy, 0);
        }
        void pushdown(int i)
        {
            if (lazy[i] > eps)
            {
                tree[i << 1] += lazy[i], tree[i << 1 | 1] += lazy[i];
                lazy[i << 1] += lazy[i], lazy[i << 1 | 1] += lazy[i];
                lazy[i] = 0;
            }
        }
        void update(int i, int l, int r, int L, int R, double k)
        {
            if (L == l && R == r)
            {
                tree[i] += k;
                lazy[i] += k;
                return;
            }
            pushdown(i);
            int mid = (l + r) >> 1;
            if (R <= mid)
                update(i << 1, l, mid, L, R, k);
            else if (L > mid)
                update(i << 1 | 1, mid + 1, r, L, R, k);
            else
                update(i << 1, l, mid, L, mid, k), update(i << 1 | 1, mid + 1, r, mid + 1, R, k);
            tree[i] = min(tree[i << 1], tree[i << 1 | 1]);
        }
        double query(int i, int l, int r, int L, int R)
        {
            if (L == l && r == R)
                return tree[i];
            pushdown(i);
            int mid=(l+r)>>1;
            if(R<=mid) return query(i<<1,l,mid,L,R);
            else if(L>mid) return query(i<<1|1,mid+1,r,L,R);
            else return min(query(i<<1,l,mid,L,mid),query(i<<1|1,mid+1,r,mid+1,R));
        }
    } ac;
    
    int main()
    {
        int ncase;
        scanf("%d", &ncase);
        while (ncase--)
        {
            int n;
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            MSET(pos,0);
            for (int i = 1; i <= n; i++)
            {
                pre[i]=pos[a[i]];
                pos[a[i]]=i;
            }
            double l = 0, r = 1.0,res;
            while (fabs(l-r)>eps)
            {
                ac.init();
                double mid = (l + r) / 2;
                bool flag = false;
                for (int i = 1; i <= n; i++)
                {
                    ac.update(1, 1, n, i, i, mid *i);
                    ac.update(1,1,n,pre[i]+1,i,1.0);
                    double ans=ac.query(1,1,n,1,i);
                    if(ans<=mid*(i+1)) 
                    {
                        flag=true;
                        break;
                    }   
                }
                if(flag) r=mid,res=mid;
                else l=mid;
            }
            printf("%lf
    ",res);
        }
        return 0;
    }
    
    
  • 相关阅读:
    交通运输线(LCA)
    POJ 2186 Popular cows(Kosaraju+强联通分量模板)
    Codeforces 351D Jeff and Removing Periods(莫队+区间等差数列更新)
    Codeforces 375D
    Codeforces 86D
    SPOJ D-query(莫队算法模板)
    Educational Codeforces Round 25 D
    Codeforces Round #423 Div. 2 C-String Reconstruction(思维)
    HDU3974 Assign the task(多叉树转换为线段+线段树区间染色)
    bzoj 2463: [中山市选2009]谁能赢呢?
  • 原文地址:https://www.cnblogs.com/coded-ream/p/7283692.html
Copyright © 2011-2022 走看看