HDU6070(二分+线段树区间更新)
来源:互联网 发布:安倍经济学知乎 编辑:程序博客网 时间:2024/06/11 03:19
Dirt Ratio
Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 1171 Accepted Submission(s): 519
Special Judge
Problem Description
In ACM/ICPC contest, the ”Dirt Ratio” of a team is calculated in the following way. First let’s ignore all the problems the team didn’t pass, assume the team passed X problems during the contest, and submitted Y times for these problems, then the ”Dirt Ratio” is measured as XY. If the ”Dirt Ratio” of a team is too low, the team tends to cause more penalty, which is not a good performance.
Picture from MyICPC
Little Q is a coach, he is now staring at the submission list of a team. You can assume all the problems occurred in the list was solved by the team during the contest. Little Q calculated the team’s low ”Dirt Ratio”, felt very angry. He wants to have a talk with them. To make the problem more serious, he wants to choose a continuous subsequence of the list, and then calculate the ”Dirt Ratio” just based on that subsequence.
Please write a program to find such subsequence having the lowest ”Dirt Ratio”.
Input
The first line of the input contains an integer T(1≤T≤15), denoting the number of test cases.
In each test case, there is an integer n(1≤n≤60000) in the first line, denoting the length of the submission list.
In the next line, there are n positive integers a1,a2,…,an(1≤ai≤n), denoting the problem ID of each submission.
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.
Sample Input
1
5
1 2 1 2 3
Sample Output
0.5000000000
Hint
For every problem, you can assume its final submission is accepted.
Source
2017 Multi-University Training Contest - Team 4
题意:给你一个数组,定义一个区间的价值为这个区间中出现数的个数除以这个区间的长度。让你从这个序列中找出区间价值最小的个。
解题思路:首先我们二分答案,然后judge函数怎样写呢?,也就是每次要找出一个区间,使得区间的价值小于mid,如下图(盗用的题解的官方图)
这个题解说的很简单,让我来为大家详细分析一下,怎样用线段树来解决这个问题,线段树到底要维护一个什么东西。
显而易见我们每次枚举r从左到右作为区间的右端点,我们维护每个点的一个mid * l + size(l, r)的最小值,易得每个点的mid * l值不变,size(l, r)的值会随着r变化而变化,也就是每次我们考虑当前的点作为r,那么我们我们可以分析出这个a[r]值对前面区间的影响,举个简单的例子,比如前面的序列为1 2 3 4 我们考虑当前的r = 5,a[r] = 3,那么对于区间[1, 5], [2,5],[3,5]的size值不变,因为他们都在更新a[5] = 3之前就包括了a[3] = 3,但是对于区间[4,5]的size值增加了1,因为这个区间之前没有出现过3,所以区间[4,5]整体最小值要加1.
#include <bits/stdc++.h>using namespace std;const int maxn = 60000 + 10;double inf = 100000000000.0;double eps = 0.00000000000001;double EPS = 0.00001;int n;int a[maxn];int last[maxn];struct node{ int l, r; double Min; double add;}Node[maxn<<2];void pushUp(int i){ int lson = i<<1; int rson = lson|1; Node[i].Min = min(Node[lson].Min, Node[rson].Min);}void pushDown(int i){ int lson = i<<1; int rson = lson|1; double add = Node[i].add; if(Node[lson].l == Node[lson].r) { if(Node[lson].Min - inf > eps) { Node[lson].add = 0; Node[lson].Min = add; } else { Node[lson].add = 0; Node[lson].Min += add; } } else { Node[lson].Min = Node[lson].Min + add; Node[lson].add += add; } if(Node[rson].l == Node[rson].r) { if(Node[rson].Min - inf > eps) { Node[rson].add = 0; Node[rson].Min = add; } else { Node[rson].add = 0; Node[rson].Min += add; } } else { Node[rson].Min = Node[rson].Min + add; Node[rson].add += add; } Node[i].add = 0;}void build(int i, int l, int r){ Node[i].l = l; Node[i].r = r; Node[i].Min = inf + 1.0; Node[i].add = 0; if(l == r) return; int mid = (l + r)>>1; i <<= 1; build(i, l, mid); build(i|1, mid + 1, r);}void update(int i, int l, int r, double value){ if(Node[i].l == l && Node[i].r == r) { if(l == r) { Node[i].add = 0; if(Node[i].Min - inf > eps) { Node[i].Min = value; } else Node[i].Min += value; return; } Node[i].add += value; Node[i].Min += value; return; } if(fabs(Node[i].add) > eps) pushDown(i); int f = i; i <<= 1; if(r <= Node[i].r) update(i, l, r, value); else if(l >= Node[i|1].l) update(i|1, l, r, value); else { update(i, l, Node[i].r, value); update(i|1, Node[i|1].l, r, value); } pushUp(f);}double query(int i, int l, int r){ if(Node[i].l == l && Node[i].r == r) { return Node[i].Min; } if(fabs(Node[i].add) > eps) pushDown(i); i <<= 1; if(r <= Node[i].r) return query(i, l, r); else if(l >= Node[i|1].l) return query(i|1, l, r); else { return min(query(i, l, Node[i].r), query(i|1, Node[i|1].l, r)); }}bool judge(double mid){ build(1, 1, n); memset(last, 0, sizeof(last)); for(int i = 1; i <= n; i++)//枚举r { int now = last[a[i]] + 1; last[a[i]] = i; update(1, now, i, (double)1); update(1, i, i, mid * (double)i); double Min = query(1, 1, n); double ans = mid * ((double)i + 1.0); if(Min - ans <= eps) return true; } 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 l = 0; double r = 1.0; while(fabs(l - r) > EPS) { double mid = (l + r) / 2.0; if(judge(mid)) { r = mid; } else l = mid; } printf("%.10lf\n", l); } return 0;}
- HDU6070(二分+线段树区间更新)
- hdu6070 二分+线段树
- HDU6070 二分 线段树
- hdu6070 线段树+二分
- HDU6070 Dirt Ratio(线段树+二分)
- HDU6070(线段树)
- hdu6070 Dirt Ratio(二分+线段树)
- hdu 4747 Mex(线段树区间更新+二分)
- HDU 4614 线段树(区间更新)+二分
- (hdu6070)2017杭电多校联赛第四场-Dirt Ratio 线段树+二分
- hdu6070 Dirt Ratio (线段树:二分+多次建树+构造难想)
- hdu6070 二分+线段树 2017多校第四场1004
- hdu6070 多校第四场 线段树+二分
- HDU6070(分数规划+线段树)
- hdu-4614-Vases and Flowers(线段树,区间更新区间查询,lazy,二分)
- HDU 2871 Memory Control(线段树区间更新,延迟更新+vector+二分)
- 线段树(单点更新+区间更新)
- HDU 4893 Wow! Such Sequence! (线段树单点更新+区间更新+区间查询+二分)
- 树状数组简介(洛谷P3368、P3374)
- Color Length UVA
- Windows 下部署Jenkins相关插件总结
- 自动打包ipa文件,上传fir.im托管平台
- 全志R16平台的androidM系统下调通GC0308(分色排版)
- HDU6070(二分+线段树区间更新)
- UVA 489
- [ASP.NET]视频总结
- LinearLayout 不能转换为 Button 另一种情况
- HTTP 所有请求方法和get与post的区别
- 使用FormData上传文件
- apache commons工具类简介
- 排序算法之快排
- 1180: 成绩统计(结构体专题)