HDU 6070 二分+线段树
Dirt Ratio
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 335 Accepted Submission(s): 105
Special Judge
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''.
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.
For every problem, you can assume its final submission is accepted.
题意:给你一个长度为n的区间 X=区间不同数的个数 Y=区间长度 求子区间X/Y的最小值
题解:二分答案mid check X/Y<=mid
X/Y=X/(r-L+1)<=mid
=> X+L*mid<=(r+1)*mid
建树初始每个点的maxn为L*mid
从左向右遍历右边界 遍历到r 更新(last[r]+1,r) 值增加1 last[r]表示a[r]相同值的上一个位置
r之前的每个结点L存的是L到r不同数的个数X+L*mid (这些便是不等式的左边)取最小值 与 (r+1)*mid 比较
- #pragma comment(linker, "/STACK:102400000,102400000")
- #include <bits/stdc++.h>
- #include <cstdlib>
- #include <cstdio>
- #include <iostream>
- #include <cstdlib>
- #include <cstring>
- #include <algorithm>
- #include <cmath>
- #include <cctype>
- #include <map>
- #include <set>
- #include <queue>
- #include <bitset>
- #include <string>
- #include <complex>
- #define LL long long
- #define mod 1000000007
- using namespace std;
- int t;
- int n;
- int a[];
- int last[];
- map<int,int> mp;
- struct node
- {
- int l,r;
- double maxn;
- int add;
- } tree[];
- void buildtree(int root ,int left,int right,double zz)
- {
- tree[root].l=left;
- tree[root].r=right;
- tree[root].add=;
- if(left==right)
- {
- tree[root].maxn=left*zz;
- return ;
- }
- int mid=(left+right)>>;
- buildtree(root<<,left,mid,zz);
- buildtree(root<<|,mid+,right,zz);
- tree[root].maxn=min(tree[root<<].maxn,tree[root<<|].maxn);
- }
- void pushdown(int root)
- {
- if(tree[root].add==) return ;
- tree[root<<].add+=tree[root].add;
- tree[root<<|].add+=tree[root].add;
- tree[root<<].maxn+=tree[root].add;
- tree[root<<|].maxn+=tree[root].add;
- tree[root].add=;
- }
- void update(int root,int left,int right,int c)
- {
- if(tree[root].l==left&&tree[root].r==right)
- {
- tree[root].add+=c;
- tree[root].maxn+=c;
- return ;
- }
- pushdown(root);
- int mid=(tree[root].l+tree[root].r)>>;
- if(right<=mid)
- {
- update(root<<,left,right,c);
- }
- else
- {
- if(left>mid)
- update(root<<|,left,right,c);
- else
- {
- update(root<<,left,mid,c);
- update(root<<|,mid+,right,c);
- }
- }
- tree[root].maxn=min(tree[root<<].maxn,tree[root<<|].maxn);
- }
- double query(int root,int left,int right)
- {
- if(left>right)
- return ;
- if(tree[root].l==left&&tree[root].r==right)
- {
- return tree[root].maxn;
- }
- pushdown(root);
- int mid=(tree[root].l+tree[root].r)>>;
- if(right<=mid)
- return query(root<<,left,right);
- else
- {
- if(left>mid)
- return query(root<<|,left,right);
- else
- return min(query(root<<,left,mid),query(root<<|,mid+,right));
- }
- }
- bool check (double x)
- {
- buildtree(,,n,x);
- for(int i=; i<=n; i++)
- {
- update(,last[i]+,i,);
- double zha=(double)query(,,i);
- if(zha<=(i+)*x)
- return true;
- }
- return false;
- }
- int main()
- {
- scanf("%d",&t);
- for(int kk=;kk<=t;kk++){
- scanf("%d",&n);
- mp.clear();
- for(int i=; i<=n; i++){
- scanf("%d",&a[i]);
- last[i]=mp[a[i]];
- mp[a[i]]=i;
- }
- double l=,r=1.0,mid,ans;
- while(abs(l-r)>=0.00001)
- {
- mid=(l+r)/;
- if(check(mid)){
- ans=mid;
- r=mid;
- }
- else
- l=mid;
- }
- printf("%f\n",ans);
- }
- return ;
- }
HDU 6070 二分+线段树的更多相关文章
- K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)
大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...
- hdu6070 Dirt Ratio 二分+线段树
/** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...
- HDU4614 Vases and Flowers 二分+线段树
分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...
- hdu 4031 attack 线段树区间更新
Attack Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)Total Subm ...
- hdu 4288 离线线段树+间隔求和
Coder Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- hdu 3016 dp+线段树
Man Down Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- J - Joseph and Tests Gym - 102020J (二分+线段树)
题目链接:https://cn.vjudge.net/contest/283920#problem/J 题目大意:首先给你n个门的高度,然后q次询问,每一次询问包括两种操作,第一种操作是将当前的门的高 ...
- Educational Codeforces Round 61 D 二分 + 线段树
https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...
- 【BZOJ-3110】K大数查询 整体二分 + 线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6265 Solved: 2060[Submit][Sta ...
随机推荐
- ipmitool命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/EricDing/p/8995263.html [root@localhost ~]# yum install -y i ...
- No.1001_第六次团队会议
黯淡的一日 今天发生了很令人不爽的一件事,杜正远又被叫去实验室了.昨天界面就很难做,而且我们组人手稀缺,他的缺席让我很难做下去. 今天开会我自己没做出什么来,就加了一个群组的添加功能,同样,曾哲昊也没 ...
- 2017-2018-2 1723 『Java程序设计』课程 结对编程练习_四则运算
一.结对对象 姓名:侯泽洋 学号:20172308 担任角色:驾驶员(侯泽洋) 伙伴第一周博客地址 二.本周内容 1.程序需求 (1).自动生成题目 可独立使用(能实现自己编写测试类单独生成题目的功能 ...
- 软件共享平台的NABCD
Need: 我感觉我们这个软件很适合现在的大学生,特别是大一大二的学生,由于在大学里面学生都在各忙各的,学生遇到问题如果自己在网上查找,这就需要花费大量的时间,如果有了这个软件学生和老师都可以在这个平 ...
- 一个关于狗记录的Java练习
package 狗场;import java.util.*;public class dogRoom { /** * 作者.范铭祥 * 狗场的狗体重查询问题 */ public static void ...
- 【转】Verilog HDL常用建模方式——《Verilog与数字ASIC设计基础》读书笔记(四)
Verilog HDL常用建模方式——<Verilog与数字ASIC设计基础>读书笔记(四) Verilog HDL的基本功能之一是描述可综合的硬件逻辑电路.所谓综合(Synthesis) ...
- quartz任务管理
导入quartz相关jar包后,要执行任务的类须实现Job接口 package quartz; import org.quartz.Job; import org.quartz.JobExecutio ...
- 【Linux笔记】CentOS 7 systemctl、firewalld
一.CentOS7 systemctl 在CentOS7中,进行chkconfig命令操作时会发现有类似“systemctl.....”的提示,systemctl可以简单实现service和chkco ...
- BZOJ5089 最大连续子段和(分块)
假设所有操作都是对整个序列的.考虑每个子区间,区间和与其被加的值构成一次函数关系.最大子段和相当于多个子区间取最大值,答案显然就在这些一次函数构成的下凸壳上.如果预处理出凸壳,只要在凸壳上暴力跳就可以 ...
- c# 方法参数 params 的试用
//添加方法 public void test(params string[] messages) { } //调用方法 test("aaa","bbb",&q ...