hdu6070

题意

给出 \(n\) 个数, \(\frac{x}{y}\) 表示某个区间不同数的个数除以区间的长度,求 \(\frac{x}{y}\) 最小值。

分析

设 \(size(l, r)\) 表示 \([l, r]\) 这个区间内不同数的个数,那么求得就是 \(\frac{size(l, r)}{r - l + 1}\) 的最小值。

二分答案 \(mid\) ,式子转化成 \(size(l, r) + mid \times l \leq mid \times (r + 1)\) 。

枚举右端点 \(r\),线段树存的是从 \(l\) 到 当前枚举到的 \(r\) 的 \(size(l, r) + mid \times l\) ,如果存在最小值满足小于等于 \(mid \times (r + 1)\) ,说明这个 \(mid\) 可以取到,更新 \(mid\) 。

新姿势:线段树内每个点的信息是动态的,和枚举到的 \(r\) 有关,通过区间更新就可以很方便的计算 \(size(l, r)\) 的值。

\(last[a[i]]\) 表示 \(a[i]\) 这个数上一次出现的位置,那么每次我们只需要区间更新 \([last[a[i]] + 1, i]\) 就好了。

code

#include<bits/stdc++.h>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
using namespace std;
const int MAXN = 6e4 + 10;
int a[MAXN];
int last[MAXN];
double s[MAXN << 2];
double lazy[MAXN << 2];
void pushDown(int rt) {
if(lazy[rt] > 0) {
s[rt << 1] += lazy[rt];
s[rt << 1 | 1] += lazy[rt];
lazy[rt << 1] += lazy[rt];
lazy[rt << 1 | 1] += lazy[rt];
lazy[rt] = 0;
}
}
void pushUp(int rt) {
s[rt] = min(s[rt << 1], s[rt << 1 | 1]);
}
void update(int L, int R, double c, int l, int r, int rt) {
if(L <= l && r <= R) {
lazy[rt] += c;
s[rt] += c;
return;
}
int m = (l + r) / 2;
pushDown(rt);
if(L <= m) update(L, R, c, lson);
if(R > m) update(L, R, c, rson);
pushUp(rt);
}
double query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
return s[rt];
}
int m = (l + r) / 2;
pushDown(rt);
double res = 1e12;
if(L <= m) res = query(L, R, lson);
if(R > m) res = min(res, query(L, R, rson));
pushUp(rt);
return res;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
double l = 0, r = 1.0, mid;
while(r - l > 1e-5) {
mid = (l + r) / 2.0;
memset(s, 0, sizeof s);
memset(lazy, 0, sizeof lazy);
memset(last, 0, sizeof last);
int flg = 0;
for(int i = 1; i <= n; i++) {
update(last[a[i]] + 1, i, 1, 1, n, 1);
update(i, i, mid * i, 1, n, 1);
if(query(1, i, 1, n, 1) <= mid * (i + 1)) {
flg = 1;
break;
}
last[a[i]] = i;
}
if(flg) r = mid;
else l = mid;
}
printf("%.6f\n", mid);
}
return 0;
}

hdu6070的更多相关文章

  1. hdu6070 Dirt Ratio 二分+线段树

    /** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...

  2. 2017 Multi-University Training Contest - Team 4 hdu6070 Dirt Ratio

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6070 题面: Dirt Ratio Time Limit: 18000/9000 MS (Ja ...

  3. 【二分】【线段树】hdu6070 Dirt Ratio

    size(l,r)表示区间l,r权值的种类数,让你求min{size(l,r)/(r-l+1)}(1<=l<=r<=n). last[r]表示a[r]上一次出现的位置, 就是二分验证 ...

  4. hdu6070(分数规划/二分+线段树区间更新,区间最值)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意: 给出一个题目提交序列, 从中选出一个正确率最小的子串. 选中的子串中每个题目当且仅当最 ...

  5. HDU-6070 Dirt Ratio(二分+线段树+分数规划)

    目录 目录 思路: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 目录 题意:传送门  原题目描述在最下面.  求\(sum/len\)最小值.\(sum\)是一段区间内不同数字的 ...

随机推荐

  1. 【题解】Bzoj4316小C的独立集

    决定要开始学习圆方树 & 仙人掌相关姿势.加油~~ 其实感觉仙人掌本质上还是一棵树,长得也还挺优美的.很多的想法都可以往树的方面上靠,再针对仙人掌的特性做出改进.这题首先如果是在树上的话那么实 ...

  2. 皮肤包项目的 Gradle 脚本演化

    我在做的一个项目需要有换肤功能,换肤的方案是采用第三方库 ThemeSkinning 的实现(在其基础上修复若干 bug).皮肤的制作是把相关的资源放在一个 app module 中打包成 apk,当 ...

  3. GDI+小例子

    原文链接地址:http://www.cnblogs.com/chuanzifan/archive/2011/11/26/2264507.html 1.在stdafx.h中 #include <G ...

  4. 接到新数据库时,分析业务常用的SQL语句

    USE DataBaseName--清空当前GridView显示,释放内存: SELECT GETDATE() --数据库关系图 SELECT * FROM sysdiagrams --列出所有表 S ...

  5. 如何抓取开了gzip的网页

    有时候用 file_get_contents() 函数抓取网页会发生乱码现象.有两个原因会导致乱码,一个是编码问题,一个是目标页面开了Gzip. 编码问题好办,把抓取到的内容转下编码即可($conte ...

  6. ionic安装遇到的一些问题

    ionic = Cordova + Angular + ionic CSS // 安装(失败的话 Mac 尝试使用 sudo,Windows 尝试管理员身份运行 cmd)$ npm install - ...

  7. bzoj 2756 [SCOI2012]奇怪的游戏 二分+网络流

    2756:[SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 4926  Solved: 1362[Submit][Stat ...

  8. ansible 部署jdk

    playbook 剧本如下 [root@sz_fy_virt_encrypt_33_239 x]# cat jdk.yml - hosts: web remote_user: opsadmin bec ...

  9. [洛谷P3501] [POI2010]ANT-Antisymmetry

    洛谷题目链接:[POI2010]ANT-Antisymmetry 题目描述 Byteasar studies certain strings of zeroes and ones. Let be su ...

  10. bzoj 2064 DP

    这道题可以抽象成两个数列,将一个数列变换为另一个 数列的代价最小 首先我们可以处理出所有的状态代表,对于每个状态 用二进制来表示,代表的是两个数列中的每一项选还是不选 那么答案最多为n1+n2-2,也 ...