hdu 6070 二分答案+线段树
来源:互联网 发布:算法导论适合初学者吗 编辑:程序博客网 时间:2024/06/06 16:37
题意: 区间价值为 区间元素种类数 / 区间长度 问最小价值的区间是?
思路:直接求解很困难,考虑二分答案判断,注意这题的关键是将二分答案后的不等式进行变换,如官方题解。二分答案 mid,检验是否存在一个区间满足 size(l,r)/(r−l+1) ≤ mid,也就是 size(l, r) + mid × l ≤mid × (r + 1)。
之后的问题就很好解决了,枚举右端点,开一颗线段树来维护到当前节点的区间不同数(类似树状数组求区间不同数的想法来加入一个新点,主要是通过一个数组维护上一次出现的位置)+ mid × l ,这样就可以轻松判断是否存在解了。
代码:
#include<bits/stdc++.h>using namespace std;#define MEM(a,b) memset(a,b,sizeof(a))#define bug puts("bug");inline int ll(int k) {return 2*k;}inline int rr(int k) {return 2*k+1;}inline int mid(int kk1,int kk2) {return (kk1+kk2)>>1;}const int maxn=3e6+10;struct pr { double sum,lazy; int left,right;}tr[maxn+10];void pushdown(int k) { if(tr[k].lazy>1e-9){ tr[ll(k)].sum+=tr[k].lazy;tr[rr(k)].sum+=tr[k].lazy; tr[ll(k)].lazy+=tr[k].lazy; tr[rr(k)].lazy+=tr[k].lazy; tr[k].lazy=0; }}void build(int k,int s,int t,double MI) { tr[k].left=s;tr[k].right=t; if(s==t) {tr[k].sum=t*MI;return;} build(ll(k),s,mid(s,t),MI); build(rr(k),mid(s,t)+1,t,MI); tr[k].sum=min(tr[ll(k)].sum,tr[rr(k)].sum); tr[k].lazy=0;}void modify(int k,int s,int t,int x) { int l=tr[k].left,r=tr[k].right; if(l==s&&r==t) { tr[k].lazy+=x,tr[k].sum+=x; return ; } pushdown(k); int mi=mid(l,r); if(t<=mi) modify(ll(k),s,t,x); else if(s>mi) modify(rr(k),s,t,x); else modify(ll(k),s,mi,x),modify(rr(k),mi+1,t,x); tr[k].sum=min(tr[ll(k)].sum,tr[rr(k)].sum);}double query(int k,int s,int t) { int l=tr[k].left,r=tr[k].right; if(l==s&&r==t) return tr[k].sum; pushdown(k); int mi=mid(l,r); double res=1e20; if (t<=mi) res=query(ll(k),s,t); else if(s>mi) res=query(rr(k),s,t); else res=min(query(ll(k),s,mi),query(rr(k),mi+1,t)); return res;}int a[700000],last[700000],t,n;int cal(double x){ build(1,1,n,x); MEM(last,0); for(int i=1;i<=n;i++){ modify(1,last[a[i]]+1,i,1); last[a[i]]=i; if(query(1,1,i)<=x*(i+1)) return 1; } return 0;}int main(){ scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); double L=0,R=1.0,mi; for(int i=0;i<25;i++){ mi=(L+R)/2; if(cal(mi)) R=mi; else L=mi; } printf("%.8f\n",R); } return 0;}
阅读全文
1 3
- hdu 6070 二分答案+线段树
- hdu-6070 _Dirt Ratio (二分答案+线段树维护)
- hdu 6070 Dirt Ratio(线段树+二分答案)
- 2017多校训练赛第四场 HDU 6070(二分答案+线段树+扫描线)
- HDU 6070 二分+线段树
- hdu 6070二分+线段树
- [BZOJ4552]二分答案+线段树
- hdu 6070 枚举答案+线段树
- HDU 6070 Dirt Ratio 线段树 二分
- HDU 6070 Dirt Ratio [二分+线段树]
- hdu 6070 Dirt Ratio 二分,线段树
- hdu 6070 Dirt Ratio(线段树+二分)
- hdu 6070 Dirt Ratio二分 线段树
- HDU 6070 二分查找 + 线段树 + 枚举
- HDU 6070 Dirt Ratio 线段树 + 二分
- 【HDU 6070 Dirt Ratio】 二分 & 线段树
- HDU 6070 Dirt Ratio 二分+线段树
- hdu 6070 二分+线段树维护
- libmali-xlnx_git.bb:do_fetch) failed with exit code '1'
- Android Studio之通过AndroidManifes.xml添加权限
- Python学习笔记(3)——Taking a Vacation
- MyBatis jdbcType类型
- 爬动的蠕虫
- hdu 6070 二分答案+线段树
- C++虚函数,纯虚函数的继承
- Libigl实现CPU间的并行
- 84. Largest Rectangle in Histogram
- Leveldb实现原理
- RDD理解及宽依赖和窄依赖
- hdu6075(思维水题)
- JDK1.8时间接口
- 离散事件模拟-银行管理