2017多校四 1004题 hdu 6070 Dirt Ratio 二分 + 线段树 + 分数规划
来源:互联网 发布:淘宝延长收获时间规则 编辑:程序博客网 时间:2024/05/28 23:22
题目链接
题意:
给定一个数列 a 长度为 n (n <= 6e5, a1, a2, ..., an <= n),求其子串中 出现的不同数字个数 与 子串的长度 之比的最小值。
这道题的特殊之处在于其是special judge
Output
For each test case, print a single line containing a floating number, denoting the lowest ''Dirt Ratio''. The answer must be printed with an absolute error not greater than 10−4 .
如果有什么正经(雾)的做法,那么这个值应该是个定值啊,不至于会............
故:二分!
二分后怎么check呢...赛后看题解(。
题解如是说:
二分答案mid,检验是否存在一个区间满足r−l+1size(l,r)≤mid,也就是size(l,r)+mid×l≤mid×(r+1)。
从左往右枚举每个位置作为r,当r变化为r+1时,对size的影响是一段区间加1,线段树维护区间最小值即可。
再说明白一点,当处理到第 i 个数时,线段树中中每个节点的值的含义为:
1. 每个叶子节点 [L, L] 的值为 [L, i] 一段的 val,
2. 每个非叶子结点 [L, R] 的值为 min{ [l, i].val | L <= l <= R }.
想明白这一点就好写了
Code:
#include <bits/stdc++.h>#define maxn 60010#define inf 0x3f3f3f3f#define eps 1e-5#define lson (rt << 1)#define rson (rt << 1 | 1)struct tree { int l, r, tag; double val;}tr[maxn * 4];double v;int n, pre[maxn], pos[maxn];inline int midi(int a, int b) { return a + b >> 1; }inline double min(double a, double b) { return a < b ? a : b; }void build(int rt, int l, int r, double x) { tr[rt].l = l; tr[rt].r = r; tr[rt].val = x * l; tr[rt].tag = 0; if (l == r) return; int mid = midi(l, r); build(lson, l, mid, x); build(rson, mid + 1, r, x);}inline void push_up(int rt) { tr[rt].val = min(tr[lson].val, tr[rson].val);}inline void push_down(int rt) { if (tr[rt].tag) { tr[lson].tag += tr[rt].tag; tr[lson].val += tr[rt].tag; tr[rson].tag += tr[rt].tag; tr[rson].val += tr[rt].tag; tr[rt].tag = 0; }}void modify(int rt, int l, int r, int r0) { if (tr[rt].l == l && tr[rt].r == r) { tr[rt].tag += 1; tr[rt].val += 1; return; } push_down(rt); int mid = midi(tr[rt].l, tr[rt].r); if (r <= mid) modify(lson, l, r, r0); else if (l > mid) modify(rson, l, r, r0); else { modify(lson, l, mid, r0); modify(rson, mid + 1, r, r0); } push_up(rt);}void query(int rt, int r) { if (tr[rt].r <= r) { v = min(v, tr[rt].val); return; } if (tr[rt].l == tr[rt].r) return; push_down(rt); int mid = midi(tr[rt].l, tr[rt].r); query(lson, r); if (r > mid) query(rson, r); push_up(rt);}bool check(double x) {// printf("x : %.3f\n", x); build(1, 1, n, x); for (int r = 1; r <= n; ++r) { modify(1, pre[r] + 1, r, r); v = inf; query(1, r); if (v <= (r + 1) * x) {// printf("%d\n", r); return true; } } return false;}void work() { memset(pos, 0, sizeof(pos)); scanf("%d", &n); for (int i = 1; i <= n; ++i) { int x; scanf("%d", &x); pre[i] = pos[x]; pos[x] = i; } double l = 0, r = 1.0, mid; while (r - l > eps) { mid = (l + r) / 2; if (check(mid)) r = mid; else l = mid; } printf("%.10f\n", mid);}int main() { int T; scanf("%d", &T); while (T--) work(); return 0;}
阅读全文
0 0
- 2017多校四 1004题 hdu 6070 Dirt Ratio 二分 + 线段树 + 分数规划
- HDU-6070 Dirt Ratio(二分+线段树+分数规划)
- Hdu 6070 Dirt Ratio【分数规划+二分+线段树】好题~好题~
- HDU 6070 Dirt Ratio【分数规划】【线段树】
- HDU 6070 Dirt Ratio 分数规划 二分 线段树维护区间最值
- 2017多校第4场 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多校4)1004/hdu-6070 Dirt Ratio(二分 + 线段树)
- hdu 6070 Dirt Ratio(二分+线段树维护区间最小值)
- HDU 6070 Dirt Ratio(二分+线段树)
- HDU 6076 Security Check(分情况DP)
- Prime Ring Problem UVA
- JPEG 2000学习笔记(1)
- 如何将多个小字符串拼接成一个大字符串
- HDU6048Puzzle
- 2017多校四 1004题 hdu 6070 Dirt Ratio 二分 + 线段树 + 分数规划
- html javascipt对象
- mac 下安装java环境
- 函数指针与状态机的用法
- device-independent bitmap (DIB) 设备无关位图
- HTML页面元素的隐藏方法
- Handler、Loop、MessageQueue的工作原理<温故知新>
- Java8 in action(1) 通过行为参数化传递代码--lambda代替策略模式
- iOS开发 非常全的三方库、插件、大牛博客等等