HDU 6070 Dirt Ratio

队友已经写过一个代码了,用数组实现的线段树,自己再写了一个结构体的线段树,嗯,就是这样,线段树风格不一样而已。

 

题解:满足的关系:res=size(l--->r) /  (r-l+1) ,求得最小的结果。正面解题,因为不知道res,而这样做的枚举每一个区间会得到n2的复杂度,所以枚举每一个可能的答案,然后再找是否存在可以满足的这样解的区间,如果不存在,那就根据枚举的mid和siza(l--->r) /(r-l+1)的关系更改mid的值。这道题目是满足单调性的,所以可以二分答案去做。

参考代码:

#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <queue>
#include <stack>
#include <iostream>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=100010;
struct node
{
    int l,r;
    double sum,lazy;
    void update(double x)
    {
        sum+=x;
        lazy+=x;
    }
}tree[maxn*4];
void push_up(int x)
{
    tree[x].sum=min(tree[x<<1].sum,tree[x<<1|1].sum);
}
void push_down(int x)
{
    double lazyval=tree[x].lazy;
    if(lazyval>1e-9)
    {
        tree[x<<1].update(lazyval);
        tree[x<<1|1].update(lazyval);
        tree[x].lazy=0;
    }
}
void build(int x,int l,int r,double Mid)
{
    tree[x].l=l,tree[x].r=r;//,tree[x].sum=0;

    if(r==l) tree[x].sum=Mid*l;
    else
    {
        int mid=(l+r)>>1;
        build(x<<1,l,mid,Mid);
        build(x<<1|1,mid+1,r,Mid);
        tree[x].lazy=0;
        push_up(x);
    }
}
void update(int x,int ql,int qr,double val)
{
    int L=tree[x].l,R=tree[x].r;
    if(ql<=L&&R<=qr)
        tree[x].update(val);
    else
    {
        push_down(x);
        int mid=(L+R)>>1;
        if(mid>=ql) update(x<<1,ql,qr,val);
        if(qr>mid) update(x<<1|1,ql,qr,val);
        push_up(x);
    }
}
double query(int x,int ql,int qr)
{
    int L=tree[x].l,R=tree[x].r;
    if(ql<=L&&R<=qr)
        return tree[x].sum;
    else
    {
        push_down(x);
        double ans=1e20;
        int mid=(L+R)>>1;
        if(mid>=ql) ans=min(ans,query(x<<1,ql,qr));
        if(qr>mid) ans=min(ans,query(x<<1|1,ql,qr));
        //push_up(x);
        return ans;
    }
}
int n,a[maxn],last[maxn];
int fun(double mid)
{
    build(1,1,n,mid);
    memset(last,0,sizeof(last));
    for(int i=1;i<=n;i++)
    {
        update(1,last[a[i]]+1,i,1);
        last[a[i]]=i;
        //printf("%lf %lf\n",query(1,1,i),mid*(i+1));
        if(query(1,1,i)<=(double)mid*(i+1))
            return 1;
    }
    return 0;
}
int  main()
{
    //freopen("C:\\Users\\Administrator\\Desktop\\a.txt","r",stdin);
    //freopen("C:\\Users\\Administrator\\Desktop\\b.txt","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        double mid=0.0,l=0.0,r=1.0,ans=0.0;
        for(int i=0;i<20;i++)
        {
            mid=(l+r)/2;
            if(fun(mid)) r=mid,ans=mid;
            else l=mid;
        }
        printf("%.10lf\n",ans);
    }
    return 0;
}

 

  

posted @ 2017-08-05 00:30  MeowMeowMeow  阅读(136)  评论(0编辑  收藏  举报