HDU6070 二分 线段树
来源:互联网 发布:注音输入法 简体 mac 编辑:程序博客网 时间:2024/06/05 01:56
大致题意:
给定一个长度为n的序列,求size(l, r)/(r-l+1)最小,其中l,r指定区间, size(l, r)表示区间L到R中不同数的个数。
二分答案,下界为0,上界为1。对于mid我们check是否存在一组(l, r) 使size(l, r)/(r-l+1)<= mid 即 size(l, r)+mid*l <= (r+1)*mid。我们枚举r,然后只要求出1~r中size(l, r)+mid*l的最小值就可以进行判断了。所以我们用线段树维护区间上size(l, r)+mid*l的最小值。其中,我们用last数组记录某个数i上一次出现的位置,那么我们在枚举到某一个位置i的时候只需要向last[arr[i]]+1~i的区间中维护的最小数上加1就可以了。
#include<bits/stdc++.h>#define lson node<<1,l,l+r>>1#define rson node<<1|1,(l+r>>1)+1,rusing namespace std;const int maxn = 6e4+10;const double eps = 1e-8;double segTree[maxn<<2], tag[maxn<<2];int arr[maxn];int n;void build(int node, int l, int r, double value){ tag[node] = 0; if (l == r){ segTree[node] = 1.0*l*value; return ; } build(lson, value); build(rson, value); segTree[node] = min(segTree[node<<1], segTree[node<<1|1]);}void push_down(int node){ if (tag[node] > eps){ tag[node<<1] += tag[node]; tag[node<<1|1] += tag[node]; segTree[node<<1] += tag[node]; segTree[node<<1|1] += tag[node]; tag[node] = 0; }}void update(int node, int l, int r, int s, int e, int value){ if (s <= l && e >= r){ segTree[node] += value; tag[node] += value; return ; } push_down(node); int mid = l+r>>1; if (s <= mid) update(lson, s, e, value); if (e > mid) update(rson, s, e, value); segTree[node] = min(segTree[node<<1], segTree[node<<1|1]);}double query(int node, int l, int r, int s, int e){ if (s <= l && e >= r) return segTree[node]; push_down(node); int mid = l+r>>1; double res = 1e9; if (s <= mid) res = min(res, query(lson, s, e)); if (e > mid) res = min(res, query(rson, s, e)); return res;}int last[maxn];bool check(double mi){ build(1, 1, n, mi); memset(last, 0, sizeof(last)); for (int i = 1; i <= n; i++){ update(1, 1, n, last[arr[i]]+1, i, 1); last[arr[i]] = i; if (query(1, 1, n, 1, i) <= mi*(i+1)) return true; } return false;}int main(){ std::ios::sync_with_stdio(false); int kase; cin >> kase; while(kase--){ cin >> n; for (int i = 1; i <= n; i++) cin >> arr[i]; double l = 0, r = 1.0, mid; for (int i = 0; i < 25; i++){ mid = (l+r)/2.0; if (check(mid)) r = mid; else l = mid; } cout.setf(ios::fixed); cout << setprecision(8) << r << endl; } return 0;}
阅读全文
0 0
- hdu6070 二分+线段树
- HDU6070 二分 线段树
- hdu6070 线段树+二分
- HDU6070(二分+线段树区间更新)
- HDU6070 Dirt Ratio(线段树+二分)
- hdu6070 Dirt Ratio(二分+线段树)
- hdu6070 二分+线段树 2017多校第四场1004
- hdu6070 多校第四场 线段树+二分
- HDU6070(线段树)
- (hdu6070)2017杭电多校联赛第四场-Dirt Ratio 线段树+二分
- hdu6070 Dirt Ratio (线段树:二分+多次建树+构造难想)
- HDU6070(分数规划+线段树)
- HDU6070 Dirt Ratio (01规划+线段树)
- hdu6070
- hdu3564(二分+线段树)
- hdu4614 二分+线段树
- hdu5217Brackets【线段树,二分】
- 【HDU4614】【线段树】【二分】
- 小米云备份的正确打开方式,你学会了吗
- Android/Java XML数据格式解析的两种方式
- Python3正则表达式
- gulp的使用与遇过的坑
- ES6函数扩展
- HDU6070 二分 线段树
- opencv7-ROI
- 二分法
- Android 获取屏幕尺寸及代码设置控件大小
- Swift3:NSMutableAttributeString的Range和NSRange问题
- C# ProgressBar用法:模拟进度条
- C#读写txt文件
- Unity5.x 烘焙场景导出方法(更换lightmap曝光丢失问题)
- linux下删除软连接