HDU6070Dirt Ratio(二分+线段树)
来源:互联网 发布:网络报警平台网络诈骗 编辑:程序博客网 时间:2024/06/13 20:54
来自大佬的讲解:http://blog.csdn.net/jerans/article/details/76651326
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=6070
题意:
定义一个区间的值为(不同数的个数/区间长度),求所有区间内的最小值
有一种01分数规划的思想,二分结果值now,这样只要存在一个区间使得这个值<=now,即可
也就是 dif/(r-l+1)<=now , 这样要使dif/(r-l+1)部分尽量的小,并不好确定,转换一下
dif<=(r-l+1)*now 依旧不好确定,因为这样还是除了枚举所有的l,r,并没有什么好思路,枚举转移也不好做,如果能分开l和r,按一定顺序枚举l或r,是不是就有一些可以重复利用的东西
dif+l*now<=(r+1)*now
这样O(n)枚举每一个r,并且要快速的确定dif+l*now的最小值,l*now是个固定值,dif的求法可以用线段树实现,这样也能快速的求这两者加和的最小
线段树里保存的是每个点到当前枚举的r之间的dif值,记录每一个数和他相同的且在他之前的最后一次出现的下标pre,每次通过线段树更新pre【a【r】】和r之间(左开右闭)加一,这样就能保证每个相同的数在同一个区间内对dif的贡献只有一次。
#include<bits/stdc++.h>using namespace std;const int maxn = 60010;const double eps = 1e-7;double mid;int pre[maxn], a[maxn], n;struct SegTree{ int l, r; double val, lazy;}seg[maxn<<2];void pushup(int rt){ seg[rt].val = min(seg[rt<<1].val, seg[rt<<1|1].val); return ;}void pushdown(int rt){ if(seg[rt].lazy) { seg[rt<<1].lazy += seg[rt].lazy; seg[rt<<1|1].lazy += seg[rt].lazy; seg[rt<<1].val += seg[rt].lazy; seg[rt<<1|1].val += seg[rt].lazy; seg[rt].lazy = 0; } return ;}void build(int rt, int l, int r){ if(l == r) { seg[rt].lazy = 0; seg[rt].val = mid * l; return ; } seg[rt].lazy = 0; int m = (l + r) >> 1; build(rt<<1, l, m); build(rt<<1|1, m+1, r); pushup(rt); return ;}void update(int l, int r, int left, int right, int rt){ if(l <= left && r >= right) { seg[rt].val++; seg[rt].lazy++; return ; } pushdown(rt); int m = (left + right) >> 1; if(m >= l) update(l, r, left, m, rt<<1); if(m < r) update(l, r, m+1, right, rt<<1|1); pushup(rt); return ;}double query(int l, int r, int left, int right, int rt){ if(l <= left && r >= right) return seg[rt].val; pushdown(rt); int m = (left + right) >> 1; double res = 1e18; if(m >= l) res = min(res, query(l, r, left, m, rt<<1)); if(m < r) res = min(res, query(l, r, m+1, right, rt<<1|1)); pushup(rt); return res;}bool check(){ memset(pre, 0, sizeof(pre)); build(1, 1, n); for(int i = 1; i <= n; i++) { double tmp = mid * (i+1.0); update(pre[a[i]]+1, i, 1, n, 1); if(query(1, i, 1, n, 1) <= tmp) return true; pre[a[i]] = i; } return false;}int main(){ int t;scanf("%d", &t); while(t--) { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); double ans = 1, left = 0, right = 1.0; while(right - left >= eps) { mid = (left + right) * 0.5; if(check()) { ans = mid; right = mid - eps; } else left = mid + eps; } printf("%.10f\n", ans); } return 0;}
阅读全文
0 0
- HDU6070Dirt Ratio(二分+线段树)
- 2017多校联合四1004/hdu6070Dirt Ratio [二分+线段树]
- HDU6070Dirt Ratio
- HDU6070 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(线段树+二分)
- hdu 6070 Dirt Ratio二分 线段树
- HDU 6070 Dirt Ratio 线段树 + 二分
- 【HDU 6070 Dirt Ratio】 二分 & 线段树
- HDU 6070 Dirt Ratio 二分+线段树
- hdu6070 Dirt Ratio(二分+线段树)
- HDU 6070 Dirt Ratio(二分+线段树)
- 关于mongodb ,redis,memcache之间见不乱理还乱的关系和作用
- Secure Multi-party Computation
- 我的Linux笔记
- Linux环境下Tomcat安装
- XAMARIN Android获取WIFIMAC地址的方法
- HDU6070Dirt Ratio(二分+线段树)
- 关于springmvc接收前端日期类参数
- 获取IE版本,强于 正则USER_AGENT并向后兼容(自用)
- 欧几里德算法GCD
- jVM加载class文件的原理机制
- 菜鸟教程例题---第一题:【1,2,3,4】组成无重复的3位数
- 结合内核实现源码分析 select poll epoll区别
- Spring Data JPA实现分页Pageable的实例代码
- HDU2222 Keywords Search