题面

传送门

此题的题意不是很清晰,要注意的一点是在区间[L,R]中,默认题目编号最后一次出现的时候是AC的

比如1 2 1 2 3 ,在区间[1,4]中,第3次提交时AC第1题,第4次提交时AC第2题,故比例为2/4=0.5

所以此问题可以转化为

给定一个序列,定义区间[l,r]的值为cnt(l,r)r−l+1" role="presentation" style="position: relative;">cnt(l,r)r−l+1cnt(l,r)r−l+1,(cnt(l,r)为区间中不同元素的个数,求值最大的区间,输出其最大值

分析

1.二分答案

很明显此题用直接枚举区间的方法会超时,必须使用二分来降低时间复杂度

如果二分区间端点,则答案不存在单调性,无法二分

因此二分答案,显然答案可取的范围是[0,1)

设二分中点为mid,由题意cnt(l,r)r−l+1≤mid" role="presentation" style="position: relative;">cnt(l,r)r−l+1≤midcnt(l,r)r−l+1≤mid ([l,r]为所有区间中值最小的区间)

两边同乘化简r-l+1,移项,整理得cnt(l,r)+mid×l≤mid×(r+1)" role="presentation" style="position: relative;">cnt(l,r)+mid×l≤mid×(r+1)cnt(l,r)+mid×l≤mid×(r+1)

2.求不等式左边的值,判断mid是否可取到

对于每次二分,枚举r从1~n,对于每一个r,我们再求右端点为r的所有区间的所有区间的值中的最小值

我们维护一棵线段树,线段数的每个叶子节点l表示左端点为l,右端点为r(当前的枚举值)时的值,再统计区间[1,r]最小值

这样我们就求出了右端点为r的所有区间的值中的最小值

由于r从1~n,线段树中的值也在不断变化,我们怎么更新线段树中的值呢?

每次r+1,需要更新[r,r]这个区间,区间加mid×r" role="presentation" style="position: relative;">mid×rmid×r,

再更新[x,r]各区间的cnt值,设a上一次出现的位置为last[a],则区间[last[a]+1,r]都需要+1,因为区间内出现了一个新的数a,而对于last[a]之前的位置,由于a已经出现过,cnt值不受影响

时间复杂度分析:

二分时间复杂度为O(log21ϵ)" role="presentation" style="position: relative;">O(log21ϵ)O(log21ϵ),其中 ϵ" role="presentation" style="position: relative;">ϵϵ为精度,在此题中设ϵ=10−5" role="presentation" style="position: relative;">ϵ=10−5ϵ=10−5即可

线段树的建树时间复杂度为O(nlog2n)" role="presentation" style="position: relative;">O(nlog2n)O(nlog2n),n次插入与查询时间复杂度为O(nlog2n)" role="presentation" style="position: relative;">O(nlog2n)O(nlog2n)

所以总的时间复杂度分析为O(nlog2n×log21ϵ)" role="presentation" style="position: relative;">O(nlog2n×log21ϵ)O(nlog2n×log21ϵ)

代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. #define maxn 60005
  6. #define eps 1e-5
  7. #define INF 0x7fffffff
  8. using namespace std;
  9. int a[maxn];
  10. int pos[maxn],last[maxn];
  11. struct node{
  12. int l;
  13. int r;
  14. double mark;
  15. double v;
  16. int len(){
  17. return r-l+1;
  18. }
  19. }tree[maxn<<2];
  20. void push_up(int pos){
  21. tree[pos].v=min(tree[pos<<1].v,tree[pos<<1|1].v);
  22. }
  23. void build(int l,int r,int pos){
  24. tree[pos].l=l;
  25. tree[pos].r=r;
  26. tree[pos].v=0;
  27. tree[pos].mark=0;
  28. if(l==r) return;
  29. int mid=(l+r)>>1;
  30. build(l,mid,pos<<1);
  31. build(mid+1,r,pos<<1|1);
  32. }
  33. void push_down(int pos){
  34. if(tree[pos].mark!=0){
  35. tree[pos<<1].v+=tree[pos].mark;
  36. tree[pos<<1|1].v+=tree[pos].mark;
  37. tree[pos<<1].mark+=tree[pos].mark;
  38. tree[pos<<1|1].mark+=tree[pos].mark;
  39. tree[pos].mark=0;
  40. }
  41. }
  42. void update(int L,int R,double v,int pos){
  43. int l=tree[pos].l,r=tree[pos].r;
  44. if(L<=l&&R>=r){
  45. tree[pos].v+=v;
  46. tree[pos].mark+=v;
  47. return;
  48. }
  49. push_down(pos);
  50. int mid=(l+r)>>1;
  51. if(L<=mid) update(L,R,v,pos<<1);
  52. if(R>mid) update(L,R,v,pos<<1|1);
  53. push_up(pos);
  54. }
  55. double query(int L,int R,int pos){
  56. int l=tree[pos].l,r=tree[pos].r;
  57. if(L<=l&&R>=r){
  58. return tree[pos].v;
  59. }
  60. push_down(pos);
  61. int mid=(l+r)>>1;
  62. double ans=INF;
  63. if(L<=mid) ans=min(ans,query(L,R,pos<<1));
  64. if(R>mid) ans=min(ans,query(L,R,pos<<1|1));
  65. return ans;
  66. }
  67. int t,n;
  68. int main(){
  69. scanf("%d",&t);
  70. while(t--){
  71. memset(last,0,sizeof(last));
  72. memset(pos,0,sizeof(pos));
  73. scanf("%d",&n);
  74. for(int i=1;i<=n;i++){
  75. scanf("%d",&a[i]);
  76. }
  77. for(int i=1;i<=n;i++){
  78. last[i]=pos[a[i]];
  79. pos[a[i]]=i;
  80. }
  81. double l=0,r=1;
  82. double ans=INF;
  83. while(fabs(l-r)>eps){
  84. build(1,n,1);
  85. double mid=(l+r)/2;
  86. bool is_min=false;
  87. for(int i=1;i<=n;i++){
  88. update(i,i,mid*i,1);
  89. update(last[i]+1,i,1,1);
  90. double t=query(1,i,1);
  91. if(mid*(i+1)>=t){
  92. is_min=true;
  93. break;
  94. }
  95. }
  96. if(is_min){
  97. r=mid;
  98. ans=min(ans,mid);
  99. }
  100. else l=mid;
  101. }
  102. printf("%lf\n",ans);
  103. }
  104. }

HDU 6070题解(二分+线段树)的更多相关文章

  1. hdu 6070 Dirt Ratio 线段树+二分

    Dirt Ratio Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Spe ...

  2. K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)

    大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...

  3. hdu6070 Dirt Ratio 二分+线段树

    /** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...

  4. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  5. Educational Codeforces Round 61 D 二分 + 线段树

    https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...

  6. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

  7. HDU4614 Vases and Flowers 二分+线段树

    分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...

  8. J - Joseph and Tests Gym - 102020J (二分+线段树)

    题目链接:https://cn.vjudge.net/contest/283920#problem/J 题目大意:首先给你n个门的高度,然后q次询问,每一次询问包括两种操作,第一种操作是将当前的门的高 ...

  9. 【BZOJ-3110】K大数查询 整体二分 + 线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Sta ...

随机推荐

  1. 7天玩转性能&接口测试

    众所周知,近10年IT领域有两个关键的风向转变,传统IT向云计算转变,传统瀑布和迭代开发模式向敏捷开发模式转变.这两个转变促成了DevOps产品交付模式的出现.互联网行业竞争激烈,许多公司专注于产品和 ...

  2. springboot poi

    pom.xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</a ...

  3. 对redis高并发测试的研究

    以下引用大神的: 测试项目: https://github.com/14251104246/redis-demo.git 准备 使用docker-compose命令启动redis服务器(可以用其他方式 ...

  4. mybaits 时间查询DATE_FORMAT

    <if test="accountdayInout.inoutDateStart!=null"> and DATE_FORMAT(t.inout_date,'%Y-%m ...

  5. 【bzoj1096】[ZJOI2007]仓库建设

    *题目描述: L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总 ...

  6. 【bzoj1179】[Apio2009]Atm

    *题目描述: *输入: 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来 ...

  7. IIS新建项目

    我在写网站的时候要 经常帮公司的游戏写界面,他们用的都是VS,然后要用IIS创建项目(配置环境)然后页面才能够在浏览器上看效果. 那就要先了解啥是IIS: IIS是Internet Informati ...

  8. window cmd 命令行下创建文件夹和文件

    新建文件夹命令: makedir 文件名 新建文件命令: type null> 文件名.文件类型 链接

  9. C++ 对象间通信框架 V2.0 ××××××× 之(三)

    类定义:CSignalSlot ======================================================================= // SignalSlo ...

  10. Fiddler抓取手机Https请求

    下载并安装Fiddler证书生成器 1.打开Fiddler—>Tools—>Telerik Fiddler Options... 2.Connections选项中勾选Allow remot ...