hdu 6070 Dirt Ratio 二分,线段树
来源:互联网 发布:淘宝直播卖东西可信吗 编辑:程序博客网 时间:2024/05/19 22:02
题目: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的贡献只有一次。
因为错在了非叶子节点的lazy数组忘记赋0,改了半天,很智障。。。
#include<bits/stdc++.h>using namespace std;const int maxn = 60005;const double eps = 1e-7;double seg[5 * maxn], lazy[5 * maxn], mid;int pre[maxn], n, a[maxn];void pushdown(int node){ if(lazy[node]) { lazy[node << 1] += lazy[node]; lazy[node << 1 | 1] += lazy[node]; seg[node << 1] += lazy[node]; seg[node << 1 | 1] += lazy[node]; lazy[node] = 0; } return ;}void pushup(int node){ seg[node] = min(seg[node << 1], seg[node << 1 | 1]); return ;}void build(int l, int r, int node){ if(l == r) { lazy[node] = 0; seg[node] = mid * l; return ; } lazy[node] = 0; int m = (l + r) >> 1; build(l, m, node << 1); build(m+1, r, node << 1 | 1 ); pushup(node); return ;}void update(int l, int r, int k, int le, int ri, int node){ if(le >= l && ri <= r) { seg[node] += k; lazy[node] += k; return ; } pushdown(node); int m = (le + ri) >> 1; if(m >= l) update(l, r, k, le, m, node << 1); if(m < r) update(l, r, k, m + 1, ri, node << 1 | 1); pushup(node); return ;}double query(int l, int r, int le, int ri, int node){ if(l <= le && r >= ri) return seg[node]; pushdown(node); int m = (le + ri) >> 1; double res = 1e18; if(m >= l) res = min(res, query(l, r, le, m, node << 1)); if(m < r) res = min(res, query(l, r, m + 1, ri, node << 1 | 1)); pushup(node); return res;}int check(){ memset(pre, 0, sizeof(pre)); build(1, n, 1); for(int i = 1; i <= n; i++) { double now = mid * (i + 1.0); update(pre[a[i]]+1, i, 1, 1, n, 1); if(query(1, i, 1, n, 1) <= now) return 1; pre[a[i]] = i; } return 0;}int main(){ int T; cin >> T; while(T--) { cin >> n; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); double ans = 1, le = 0, ri = 1; while(ri - le >= eps) { mid = (le + ri) / 2.0; if(check()) { ans = mid; ri = mid - eps; } else { le = mid + eps; } } printf("%.10lf\n", ans); } return 0;}
阅读全文
1 0
- 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(二分+线段树)
- hdu 6070 Dirt Ratio(线段树+二分答案)
- HDU 6070 Dirt Ratio (线段树+二分)
- HDU 6070 Dirt Ratio(二分+线段树)
- HDU 6070 Dirt Ratio 线段树
- HDU 6070 Dirt Ratio 分数规划 二分 线段树维护区间最值
- HDU 6070 Dirt Ratio (二分+线段树, 2017 Multi-Univ Training Contest 4)
- hdu 6061 NTT
- 网易2017年校招笔试题--最大奇约数
- TensorFlow学习笔记
- 微信公众平台开发——如何保证access_token长期有效?
- 《代码整洁之道》第七章——错误处理
- hdu 6070 Dirt Ratio 二分,线段树
- CSS 派生选择器 contextual selectors
- Linux curl介绍
- Struts
- Imageloader加载图片
- DTD学习笔记
- [剑指offer]变态跳台阶
- LeetCode-67-Add Binary(二进制相加)
- session和cookie学习