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;
}

  

时间: 2024-10-13 09:50:39

HDU 6070 Dirt Ratio的相关文章

hdu 6070 Dirt Ratio(分数规划)

题目链接:hdu 6070 Dirt Ratio 题意: 给你n个数,让你找一段区间[l,r],使得[l,r]中不同的数的个数size/(r-l+1)最小. 题解: Claris官方题解: 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 5 const int N=6e4+7; 6 int t,n,a[N],lazy[N*4],la[N]; 7

第四场 hdu 6070 Dirt Ratio (线段树+二分)

http://acm.hdu.edu.cn/showproblem.php?pid=6070 题目大意:给出的序列上的数代表颜色,求子序列中不同数字的个数X与子序列长度Y中,X/Y的最小值 解题思路:思路和官方给的想法一样 值得注意的是线段树的节点中储存的是 size(l,r)+mid×l ,在建树时 mid×l 作为树节点的初始值,然后不断更新当前颜色对于 前一个相同颜色的位置+1 到 当前位置 的节点值+1,然后询问 1 到 当前位置的最小值 是否小于mid*(i+1). 虽然最后要打印小数

hdu 2489 Minimal Ratio Tree(dfs枚举 + 最小生成树)~~~

题目: 链接:点击打开链接 题意: 输入n个点,要求选m个点满足连接m个点的m-1条边权值和sum与点的权值和ans使得sum/ans最小,并输出所选的m个点,如果有多种情况就选第一个点最小的,如果第一个点也相同就选第二个点最小的........ 思路: 求一个图中的一颗子树,使得Sum(edge weight)/Sum(point weight)最小~ 数据量小,暴力枚举~~~~~dfs暴力枚举C(M,N)种情况. 枚举出这M个点之后,Sum(point weight)固定,进行prim或者K

hdu 6070 线段树+二分

HDU - 6070 题意:提交了n次题目,每个题目都是最后一次提交的时候AC的,现在求一个区间,这个区间的AC率是最低的(只考虑这个区间内的题目,同样区间内最后交的一遍是AC的),求最低的AC率 思路:AC率=提交次数/题目数目,即区间长度/题目种类,siz[l,r]/(r-l+1)=p(siz[l,r]表示l r区间内的不同题目的个数,p表示AC率), 把式子做一下调整,siz[l,r]+p*l=p(r+1),二分p(0-1)用线段树维护siz[l,r]+l*p ,然后枚举r,每次更新,因为

hdu 2489 Minimal Ratio Tree 枚举+最小生成树

点的总数很小,直接枚举就好. #include <stdio.h> #include <string.h> #define N 20 #define inf 1000000 int mk[N],n,k,ans[N]; double low[N],val[N]; double map[N][N],MIN; double prim() { int i,j; double sum=0; double tot=0; for(i=1;i<=n;i++) low[i]=inf; int

HDU 2489 Minimal Ratio Tree(数据结构-最小生成树)

Minimal Ratio Tree Problem Description For a tree, which nodes and edges are all weighted, the ratio of it is calculated according to the following equation. Given a complete graph of n nodes with all nodes and edges weighted, your task is to find a

HDU 2489 Minimal Ratio Tree (dfs+Prim最小生成树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2489 Problem Description For a tree, which nodes and edges are all weighted, the ratio of it is calculated according to the following equation. Given a complete graph of n nodes with all nodes and edges

HDU 2489 Minimal Ratio Tree

Minimal Ratio Tree Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 248964-bit integer IO format: %I64d      Java class name: Maina For a tree, which nodes and edges are all weighted, the ratio of it is calcul

hdu 2489 Minimal Ratio Tree DFS枚举点+最小生成树 属于中等偏上题 ,Double比较大小的时候注意精度问题

Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2835    Accepted Submission(s): 841 Problem Description For a tree, which nodes and edges are all weighted, the ratio of it is