zoukankan      html  css  js  c++  java
  • 第四场 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)。

    虽然最后要打印小数点后九位但是精度只要达到小数点后五位就可以了。

    AC代码:4056MS

     1 #include <iostream>
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 const int maxn=60100;
     5 const double eps=1e-5;
     6 int a[maxn],flag[maxn];
     7 double val[maxn<<2],lazy[maxn<<2];
     8 int t,n;
     9 void push_up(int k)
    10 {
    11     val[k]=min(val[k*2],val[k*2+1]);
    12 }
    13 void push_down(int k)
    14 {
    15     if(lazy[k])
    16     {
    17         lazy[k*2]+=lazy[k];
    18         lazy[k*2+1]+=lazy[k];
    19         val[k*2]+=lazy[k];
    20         val[k*2+1]+=lazy[k];
    21         lazy[k]=0;
    22     }
    23 }
    24 void build(double mid,int l,int r,int k)
    25 {
    26     lazy[k]=0;
    27     if(l==r)
    28     {
    29         val[k]=l*mid;
    30         return ;
    31     }
    32     int midd=(l+r)/2;
    33     build(mid,l,midd,k*2);
    34     build(mid,midd+1,r,k*2+1);
    35     push_up(k);
    36 }
    37 void init(int L,int R,int l,int r,int k)
    38 {
    39     if(L<=l&&r<=R)
    40     {
    41         val[k]=val[k]+1;
    42         lazy[k]+=1;
    43         return ;
    44     }
    45     push_down(k);
    46     int mid=(l+r)/2;
    47     if(L<=mid) init(L,R,l,mid,k*2);
    48     if(R>mid) init(L,R,mid+1,r,k*2+1);
    49     push_up(k);
    50 }
    51 double query(int L,int R,int l,int r,int k)
    52 {
    53     if(L<=l&&r<=R)
    54     {
    55         return val[k];
    56     }
    57     push_down(k);
    58     int mid=(l+r)/2;
    59     double ans=1e5;
    60     if(L<=mid) ans=query(L,R,l,mid,k*2);
    61     if(R>mid) ans=min(ans,query(L,R,mid+1,r,k*2+1));
    62     push_up(k);
    63     return ans;
    64 }
    65 bool solve(double mid)
    66 {
    67     memset(flag,0,sizeof(flag));
    68     build(mid,1,n,1);
    69     for(int i=1;i<=n;i++)
    70     {
    71         init(flag[a[i]]+1,i,1,n,1);
    72         flag[a[i]]=i;
    73         if(query(1,i,1,n,1)<=mid*(i+1)) return true;
    74     }
    75     return false;
    76 }
    77 int main()
    78 {
    79 
    80     scanf("%d",&t);
    81     //freopen("data.txt","w",stdout);
    82     while(t--)
    83     {
    84         scanf("%d",&n);
    85         for(int i=1;i<=n;i++)
    86         scanf("%d",&a[i]);
    87         double l=0,r=1,mid,ans;
    88         while(r-l>eps)
    89         {
    90             mid=(l+r)/2;
    91             if(solve(mid))
    92             r=(ans=mid)-eps;
    93             else
    94             l=mid+eps;
    95         }
    96         printf("%.9lf
    ",ans);
    97     }
    98     return 0;
    99 }
  • 相关阅读:
    JavaScript中的memorizing技术
    在IE6/7/8下识别html5标签
    JavaScript中的类式继承和原型式继承
    OpenSUSE环境配置
    CentOS环境配置(LNMP)
    CentOS上OpenCC中文简繁体转换
    jQuery点击按钮页面滚动条向下滚动
    javascript-数组常用方法
    Tomcat配置常见错误问题解决方法
    字符串
  • 原文地址:https://www.cnblogs.com/wang-ya-wei/p/7289356.html
Copyright © 2011-2022 走看看