hdu6070 Dirt Ratio(二分+线段树)
来源:互联网 发布:java书籍顺序推荐 知乎 编辑:程序博客网 时间:2024/06/06 01:36
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070
题意:在区间[l,r]中,不同数的个数/区间长度的最小值
解:
用二分找答案最小值,用size(l,r)/(r-l+1)<=mid来判断答案是否最小。
公式可以转化为size(l,r)+l*mid<=(r+1)*mid,可以用线段树来维护l*mid的最小值。
利用线段树更新的是数字出现的次数,使用pre数组来记录时,更新新一段的区间里的次数,因为上一个相同的数字已经没有了贡献。
代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#define mem(a,b) memset(a,0,sizeof(a))using namespace std;const int maxn=6e4+50;const double esp=1e-5;int a[maxn];int pre[maxn],pos[maxn];struct Tree{ int l,r,node; double v,lazy;}seg[maxn<<2];/*void init(){ for(int i=1;i<=maxn;i++) { seg[i].v=0.0; seg[i].lazy=0.0; }}*/void pushup(int node){seg[node].v=min(seg[node<<1].v,seg[node<<1|1].v);}void pushdown(int node){ if(seg[node].lazy) { seg[node<<1].lazy+=seg[node].lazy; seg[node<<1|1].lazy+=seg[node].lazy; seg[node<<1].v+=seg[node].lazy; seg[node<<1|1].v+=seg[node].lazy; seg[node].lazy=0; } return ;}void build(int l,int r,int node,double k){ seg[node].l=l;seg[node].r=r;seg[node].lazy=0; if(l==r){ seg[node].v=k*l*1.0; return ; } int mid=(l+r)/2; build(l,mid,node<<1,k); build(mid+1,r,node<<1|1,k); pushup(node); return ;}void update(int l,int r,int node,double k){ if(seg[node].l>=l&&seg[node].r<=r) { seg[node].v+=k; seg[node].lazy+=k; return ; } pushdown(node); int mid = (seg[node].l+seg[node].r)/2; if(l<=mid) update(l,r,node<<1,k); if(r>mid) update(l,r,node<<1|1,k); pushup(node);}double query(int l,int r,int node){ if(seg[node].l>=l&&seg[node].r<=r) { return seg[node].v; } pushdown(node); int mid=(seg[node].l+seg[node].r)/2; double xx=1e9; if(l<=mid) xx=min(xx,query(l,r,node<<1)); if(r>mid) xx=min(xx,query(l,r,node<<1|1)); pushup(node); return xx;}int main(){ int t,n; scanf("%d",&t); while(t--) { scanf("%d",&n); mem(pos,0); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(pos[a[i]]) pre[i]=pos[a[i]]; else pre[i]=0; pos[a[i]]=i; } double l=0,r=1.0,mid,ans; while(r-l>esp) { mid=(l+r)/2.0; build(1,n,1,mid); int flg=0; for(int i=1;i<=n;i++) { update(pre[i]+1,i,1,1.0);/* ****** */ if(query(1,i,1)<=mid*(i+1.0)){flg=1;break;} } if(flg){ans=mid;r=mid-esp;} else l=mid+esp; } printf("%lf\n",ans); } return 0;}
阅读全文
0 0
- HDU6070 Dirt Ratio(线段树+二分)
- hdu6070 Dirt Ratio(二分+线段树)
- (hdu6070)2017杭电多校联赛第四场-Dirt Ratio 线段树+二分
- hdu6070 Dirt Ratio (线段树:二分+多次建树+构造难想)
- HDU6070 Dirt Ratio (01规划+线段树)
- HDU 6070 Dirt Ratio 线段树 二分
- HDU 6070 Dirt Ratio [二分+线段树]
- hdu 6070 Dirt Ratio 二分,线段树
- hdu 6070 Dirt Ratio(线段树+二分)
- hdu 6070 Dirt Ratio二分 线段树
- HDU 6070 Dirt Ratio 线段树 + 二分
- 【HDU 6070 Dirt Ratio】 二分 & 线段树
- HDU 6070 Dirt Ratio 二分+线段树
- HDU 6070 Dirt Ratio(二分+线段树)
- hdu6070 Dirt Ratio
- HDU6070-Dirt Ratio
- hdu6070 Dirt Ratio
- [HDU6070] Dirt Ratio
- freemarker 数字过长去掉逗号
- Android 去掉窗口标题和程序全屏
- java提高篇(十九)-----数组之二
- js复制兼容android,ios,pc
- Android模拟器DPAD not enabled in avd 启用
- hdu6070 Dirt Ratio(二分+线段树)
- Android之GPS定位详解
- Java 的Access 数据库操作库 Jackcess
- [ARM-Linux开发]mknod命令使用
- Asp.Net 数据绑定控件
- freemarker对于 null 值判断
- 根据输入日期,获得当前月的天数
- kettle调度现状、痛点及解决方法
- user-agent-utils