hdu 6070 Dirt Ratio 线段树+二分

Dirt Ratio

Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Special Judge


Problem Description
In ACM/ICPC contest, the ''Dirt Ratio'' of a team is calculated in the following way. First let's ignore all the problems the team didn't pass, assume the team passed Xproblems during the contest, and submitted Y times for these problems, then the ''Dirt Ratio'' is measured as XY. If the ''Dirt Ratio'' of a team is too low, the team tends to cause more penalty, which is not a good performance.



Picture from MyICPC


Little Q is a coach, he is now staring at the submission list of a team. You can assume all the problems occurred in the list was solved by the team during the contest. Little Q calculated the team's low ''Dirt Ratio'', felt very angry. He wants to have a talk with them. To make the problem more serious, he wants to choose a continuous subsequence of the list, and then calculate the ''Dirt Ratio'' just based on that subsequence.

Please write a program to find such subsequence having the lowest ''Dirt Ratio''.
 

 

Input
The first line of the input contains an integer T(1≤T≤15), denoting the number of test cases.

In each test case, there is an integer n(1≤n≤60000) in the first line, denoting the length of the submission list.

In the next line, there are n positive integers a1,a2,...,an(1≤ai≤n), denoting the problem ID of each submission.
 

 

Output
For each test case, print a single line containing a floating number, denoting the lowest ''Dirt Ratio''. The answer must be printed with an absolute error not greater than 10−4.
 

 

Sample Input
1 5 1 2 1 2 3
 

 

Sample Output
0.5000000000
Hint
For every problem, you can assume its final submission is accepted.
 

 

Source

官方题解:

   

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
#include<stdlib.h>
#include<time.h>
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pi (4*atan(1.0))
#define bug(x)  cout<<"bug"<<x<<endl;
#define eps 1e-4

const int N=6e4+10,M=1e6+10,inf=2147483647;
const LL INF=1e18+10,mod=998244353;
struct is
{
    double minn[N<<2];
    int lazy[N<<2];
    void pushdown(int pos)
    {
        if(lazy[pos])
        {
            minn[pos<<1]+=lazy[pos];
            minn[pos<<1|1]+=lazy[pos];
            lazy[pos<<1|1]+=lazy[pos];
            lazy[pos<<1]+=lazy[pos];
            lazy[pos]=0;
        }
    }
    void build(int l,int r,int pos,double m)
    {
        lazy[pos]=0;
        if(l==r)
        {
            minn[pos]=m*l;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,pos<<1,m);
        build(mid+1,r,pos<<1|1,m);
        minn[pos]=min(minn[pos<<1],minn[pos<<1|1]);
    }
    void update(int L,int R,int z,int l,int r,int pos)
    {
        if(L<=l&&r<=R)
        {
            minn[pos]+=z;
            lazy[pos]+=z;
            return;
        }
        pushdown(pos);
        int mid=(l+r)>>1;
        if(L<=mid)update(L,R,z,l,mid,pos<<1);
        if(R>mid) update(L,R,z,mid+1,r,pos<<1|1);
        minn[pos]=min(minn[pos<<1],minn[pos<<1|1]);
    }
    double query(int L,int R,int l,int r,int pos)
    {
        if(L<=l&&r<=R)return minn[pos];
        pushdown(pos);
        int mid=(l+r)>>1;
        double ans=99999999999;
        if(L<=mid)ans=min(ans,query(L,R,l,mid,pos<<1));
        if(R>mid)ans=min(ans,query(L,R,mid+1,r,pos<<1|1));
        return ans;
    }
}tree;
int n,pre[N],a[N];
int check(double x)
{
    tree.build(1,n,1,x);
    memset(pre,0,sizeof(pre));
    for(int i=1;i<=n;i++)
    {
        tree.update(pre[a[i]]+1,i,1,1,n,1);
        double p=tree.query(1,i,1,n,1);
        //cout<<i<<" "<<x<<" "<<p<<" "<<x*(i+1)<<endl;
        if(p<=x*(i+1))return 1;
        pre[a[i]]=i;
    }
    return 0;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        double s=0;
        double e=1,ans=-1;
        while(e-s>=eps)
        {
            double mid=(s+e)/2;
            if(check(mid))
            {
                ans=mid;
                e=mid;
            }
            else s=mid;
        }
        printf("%f\n",ans);
    }
    return 0;
}

 

posted @ 2017-08-03 18:06  jhz033  阅读(325)  评论(0)    收藏  举报