题面

传送门

此题的题意不是很清晰,要注意的一点是在区间[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ϵ)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define maxn 60005
#define eps 1e-5
#define INF 0x7fffffff
using namespace std;
int a[maxn];
int pos[maxn],last[maxn];
struct node{
int l;
int r;
double mark;
double v;
int len(){
return r-l+1;
}
}tree[maxn<<2];
void push_up(int pos){
tree[pos].v=min(tree[pos<<1].v,tree[pos<<1|1].v);
}
void build(int l,int r,int pos){
tree[pos].l=l;
tree[pos].r=r;
tree[pos].v=0;
tree[pos].mark=0;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,pos<<1);
build(mid+1,r,pos<<1|1);
}
void push_down(int pos){
if(tree[pos].mark!=0){
tree[pos<<1].v+=tree[pos].mark;
tree[pos<<1|1].v+=tree[pos].mark;
tree[pos<<1].mark+=tree[pos].mark;
tree[pos<<1|1].mark+=tree[pos].mark;
tree[pos].mark=0;
}
}
void update(int L,int R,double v,int pos){
int l=tree[pos].l,r=tree[pos].r;
if(L<=l&&R>=r){
tree[pos].v+=v;
tree[pos].mark+=v;
return;
}
push_down(pos);
int mid=(l+r)>>1;
if(L<=mid) update(L,R,v,pos<<1);
if(R>mid) update(L,R,v,pos<<1|1);
push_up(pos);
}
double query(int L,int R,int pos){
int l=tree[pos].l,r=tree[pos].r;
if(L<=l&&R>=r){
return tree[pos].v;
}
push_down(pos);
int mid=(l+r)>>1;
double ans=INF;
if(L<=mid) ans=min(ans,query(L,R,pos<<1));
if(R>mid) ans=min(ans,query(L,R,pos<<1|1));
return ans;
}
int t,n;
int main(){
scanf("%d",&t);
while(t--){
memset(last,0,sizeof(last));
memset(pos,0,sizeof(pos));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
last[i]=pos[a[i]];
pos[a[i]]=i;
}
double l=0,r=1;
double ans=INF;
while(fabs(l-r)>eps){
build(1,n,1);
double mid=(l+r)/2;
bool is_min=false;
for(int i=1;i<=n;i++){
update(i,i,mid*i,1);
update(last[i]+1,i,1,1);
double t=query(1,i,1);
if(mid*(i+1)>=t){
is_min=true;
break;
}
}
if(is_min){
r=mid;
ans=min(ans,mid);
}
else l=mid;
}
printf("%lf\n",ans);
}
}

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. vue-cli3.0以上项目中引入jquery的方法

    这里配置的是vue-cli3.0引入jquery的方法,不是vue-cli2.0的配置方法 一.安装jquery npm install jquery --save 二.在vue.config.js ...

  2. Vue最常用的组件通讯有三种:父->子组件通讯、子->父组件通讯,兄弟组件通讯.(template用的pug模板语法)

    Vue组件通讯   Vue最常用的组件通讯有三种:父->子组件通讯.子->父组件通讯,兄弟组件通讯.(template用的pug模板语法) 1.父->子组件通讯 父->子组件通 ...

  3. Eclipse设置类和方法的注释模板

    一.打开设置模板的窗口:Window->Preference->Java->Code Style->Code Template展开Comments,最常用的就是类和方法的注释, ...

  4. Java——容器(Interator)

    [Interator接口]   <1> 所有实现了Collection接口的容器类都有一个interator方法用以返回一个实现了Interaor接口的对象. <2> Inte ...

  5. LOJ504「LibreOJ β Round」ZQC 的手办

    https://loj.ac/problem/504 题解 对于区间取\(\max\),这个比较好办,直接在线段树上打标记就行了. 如果让我们弹出前\(n\)个数,我们可以用类似超级钢琴的思想,队列中 ...

  6. es的脑裂

    一个正常es集群中只有一个主节点,主节点负责管理整个集群,集群的所有节点都会选择同一个节点作为主节点:所以无论访问那个节点都可以查看集群的状态信息. 而脑裂问题的出现就是因为从节点在选择主节点上出现分 ...

  7. Scrapy 学习笔记爬豆瓣 250

    Scrapy 是比较上层的库,基于中间层开发,它基于高层,所以它依赖许多其它库.事件驱动的异步技术. Scrapy 爬取网页,以豆瓣电影 Top 250 为例子. 首先打开命令提示符,输入.scrap ...

  8. 阿里云配置通用服务的坑 ssh: connect to host 47.103.101.102 port 22: Connection refused

    1.~ wjw$ ssh root@47.103.101.102 ssh: connect to host 47.103.101.102 port 22: Connection refused ssh ...

  9. Basic Model Theory of XPath on Data Trees

    w https://openproceedings.org/2014/conf/icdt/FigueiraFA14.pdf From a database perspective, however, ...

  10. day51—JavaScript绑定事件

    转换学开发,代码100天——2018-05-06 今天学习JavaScript的绑定事件.因为浏览器的原因绑定事件需要考虑兼容性问题. attachEvent     IE浏览器 ,ie9以上事件执行 ...