HDU_6070_Dirt Ratio_二分_线段树优化
2017-08-08 14:41
357 查看
题目大意:
给一串长度为n的整数数列(1 <= ai <= n),可重复,计算连续子串的 X / Y 的最小值,X为子串中出现不同数字的个数,Y为数列长度。
思路:
在0~1内二分找最小值每次判断是否存在一个子串的值小于等于mid.
X / Y <= mid
X <= mid * Y
X <= mid * (r - l + 1)
X + mid * (l - 1) <= mid * r
从左到右枚举右界r,当枚举至当前的r时,线段树中的 0~r 区间内的保存l到当前r之间出现不同数字个数和mid * (l - 1)的和,用线段树维护区间最小值与 mid * r 比较.
用pre[]数组记录当前数字前一次出现的位置, 在pre[temp] + 1 ~ i 区间 + 1
给一串长度为n的整数数列(1 <= ai <= n),可重复,计算连续子串的 X / Y 的最小值,X为子串中出现不同数字的个数,Y为数列长度。
思路:
在0~1内二分找最小值每次判断是否存在一个子串的值小于等于mid.
X / Y <= mid
X <= mid * Y
X <= mid * (r - l + 1)
X + mid * (l - 1) <= mid * r
从左到右枚举右界r,当枚举至当前的r时,线段树中的 0~r 区间内的保存l到当前r之间出现不同数字个数和mid * (l - 1)的和,用线段树维护区间最小值与 mid * r 比较.
用pre[]数组记录当前数字前一次出现的位置, 在pre[temp] + 1 ~ i 区间 + 1
#include <iostream> #include <cstdio> #include <string.h> #define MAXN 60000 + 10 using namespace std; struct Node { double val; double lazy; } nodes[MAXN << 2]; void build (int l, int r, int root) { Node& n = nodes[root]; n.val = n.lazy = 0; if (l == r) return; int mid = (l + r) >> 1; build(l, mid, root * 2 + 1); build(mid + 1, r, root * 2 + 2); } void push_down(int l, int r, int root) { Node& n = nodes[root]; if (l == r) { n.lazy = 0; return; } else { nodes[root * 2 + 1].val += n.lazy; nodes[root * 2 + 1].lazy += n.lazy; nodes[root * 2 + 2].val += n.lazy; nodes[root * 2 + 2].lazy += n.lazy; n.lazy = 0; } } void update(int ul, int ur, double val, int l, int r, int root) { Node& n = nodes[root]; if (ul <= l && r <= ur) { nodes[root].val += val; nodes[root].lazy += val; return; } int mid = (l + r) >> 1; if (n.lazy > 0) push_down(l, r, root); if (ur <= mid) update(ul, ur, val, l, mid, root * 2 + 1); else if (ul > mid) update(ul, ur, val, mid + 1, r, root * 2 + 2); else { update(ul, ur, val, l, mid, root * 2 + 1); update(ul, ur, val, mid + 1, r, root * 2 + 2); } nodes[root].val = min(nodes[root * 2 + 1].val, nodes[root * 2 + 2].val); } double query(int ql, int qr, int l, int r, int root) { if (ql <= l && r <= qr) return nodes[root].val; int mid = (l + r) >> 1; if (nodes[root].lazy > 0) push_down(l, r, root); if (qr <= mid) return query(ql, qr, l, mid, root * 2 + 1); else if (ql > mid) return query(ql, qr, mid + 1, r, root * 2 + 2); else return min(query(ql, qr, l, mid, root * 2 + 1), query(ql, qr, mid + 1, r, root * 2 + 2)); } int a[MAXN], pre[MAXN]; int main() { int t, n; freopen("in.txt", "r", stdin); scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", a + i); double l = 0, r = 1; while (r - l > 1e-5) { build(0, n - 1, 0); memset(pre, -1, sizeof(pre)); double mid = (r + l) / (double)2; for (int i = 0; i < n; i++) update(i, i, mid * (double)(i - 1), 0, n - 1, 0); int flag = 0; for (int i = 0; i < n; i++) { int temp = a[i]; update(pre[temp] + 1, i, (double)1, 0, n - 1, 0); pre[temp] = i; if (query(0, i, 0, n - 1, 0) <= mid * (double)i) { flag = 1; break; } } if (flag) r = mid; else l = mid; } printf("%f\n", l); } }
相关文章推荐
- HDU_6070_Dirt Ratio_二分_线段树优化
- HDU 6070 Dirt Ratio (二分+线段树, 2017 Multi-Univ Training Contest 4)
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- HDU 6070 Dirt Ratio(二分+线段树 17多校第四场)
- hdu 6070 Dirt Ratio(二分+线段树维护区间最小值)
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- HDU 6070 Dirt Ratio(二分+线段树)
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- HDU 6070 Dirt Ratio(二分+线段树)
- HDU - 6070 - Dirt Ratio(二分+线段树)
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- hdu 6070 Dirt Ratio 二分,线段树
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- 2017 Multi-University Training Contest - Team 4 HDU 6070 Dirt Ratio (二分+ 线段树)
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- hdu-6070 _Dirt Ratio (二分答案+线段树维护)
- HDU 6070 Dirt Ratio 二分+线段树
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )