hdu6070(分数规划/二分+线段树区间更新,区间最值)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6070
题意: 给出一个题目提交序列, 从中选出一个正确率最小的子串. 选中的子串中每个题目当且仅当最后一次提交是正确的.
思路: 分数规划
二分答案, 然后在 check 函数中查找是否存在某个区j间 [l, r] 使得 sum(l, r) / (r - l + 1) <= mid, 即 sum(l, r) + l * mid <= (r + 1) * mid. 可以用个线段树来维护 sum(l, r) + l * mid . 建树时直接将 l * mid 放入树中, 然后从左到右枚举 r, 对于当前 i, a[i] 对区间 [pre[i] + 1, i] 的贡献为一(区间 [1, pre[i]] 内的贡献之前的a[i]已经计算了) . 这样对于当前更新后, 1 <= j <= i , sum[j] 即为区间 [j, i] 内的贡献. 那么对于当前 i, query(1, i) 就得到了所有以 i 为后缀的区间的贡献最小值. 遍历完 r 后即得到了所有区间的贡献最小值.
最后要注意一下线段树区间更新,区间最值的 lazy 数组维护写法, 最值和区间求和是不同的.
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std; const double eps = 1e-;
const int MAXN = 6e4 + ;
int a[MAXN], pre[MAXN], last[MAXN], n;
double sum[MAXN << ], lazy[MAXN << ]; void push_up(int rt){ //向上更新取最值
sum[rt] = min(sum[rt << ], sum[rt << | ]);
} void push_down(int rt){
if(lazy[rt]){//将标记向下更新,维护的是最值,sum不需要求和
lazy[rt << ] += lazy[rt];
lazy[rt << | ] += lazy[rt];
sum[rt << ] += lazy[rt];
sum[rt << | ] += lazy[rt];
lazy[rt] = ;
}
} void build(int l, int r, int rt, double value){
lazy[rt] = ;
if(l == r){
sum[rt] = value * l;
return;
}
int mid = (l + r) >> ;
build(lson, value);
build(rson, value);
push_up(rt);
} void update(int L, int R, int value, int l, int r, int rt){
if(L <= l && R >= r){
lazy[rt] += value;
sum[rt] += value;//维护的是最值,sum不需要求和
return;
}
push_down(rt);
int mid = (l + r) >> ;
if(L <= mid) update(L, R, value, lson);
if(R > mid) update(L, R, value, rson);
push_up(rt);
} double query(int L, int R, int l, int r, int rt){
if(L <= r && R >= r) return sum[rt];
push_down(rt);
double cnt = 1e5;
int mid = (l + r) >> ;
if(L <= mid) cnt = min(cnt, query(L, R, lson));
if(R > mid) cnt = min(cnt, query(L, R, rson));
return cnt;
} bool check(double mid){
build(, n, , mid);
for(int i = ; i <= n; i++){
update(pre[i] + , i, , , n, );
if(query(, i, , n, ) <= (double)mid *(i + )) return true;
}
return false;
} int main(void){
int t;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
memset(pre, , sizeof(pre));
memset(last, , sizeof(last));
for(int i = ; i <= n; i++){
scanf("%d", &a[i]);
pre[i] = last[a[i]];
last[a[i]] = i;
}
double l = , r = ;
while(r - l > eps){
double mid = (l + r) / ;
if(check(mid)) r = mid - eps;
else l = mid + eps;
}
printf("%.5lf\n", r + eps);
}
return ;
}
hdu6070(分数规划/二分+线段树区间更新,区间最值)的更多相关文章
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)
POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...
- HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)
HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...
- hdu 1166线段树 单点更新 区间求和
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu6070 Dirt Ratio 二分+线段树
/** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...
- hdu2795(线段树单点更新&区间最值)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题意:有一个 h * w 的板子,要在上面贴 n 条 1 * x 的广告,在贴第 i 条广告时要 ...
- hdu1166(线段树单点更新&区间求和模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意:中文题诶- 思路:线段树单点更新,区间求和模板 代码: #include <iost ...
- 【HDU】1754 I hate it ——线段树 单点更新 区间最值
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- POJ 2892 Tunnel Warfare(线段树单点更新区间合并)
Tunnel Warfare Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 7876 Accepted: 3259 D ...
随机推荐
- 关于ios::sync_with_stdio(false);和 cin.tie(0)加速c++输入输出流
原文地址:http://www.hankcs.com/program/cpp/cin-tie-with-sync_with_stdio-acceleration-input-and-output.ht ...
- codeforces 707D D. Persistent Bookcase(dfs)
题目链接: D. Persistent Bookcase time limit per test 2 seconds memory limit per test 512 megabytes input ...
- Android中高效的显示图片之二——在非UI线程中处理图片
在“加载大图”文章中提到的BitmapFactory.decode*方法,如果源数据是在磁盘.网络或其它任何不是在内存中的位置,那么它都不应该在UI线程中执行.因为它的加载时间不可预测且依赖于一系列因 ...
- 【遍历二叉树】09判断二叉树是否关于自己镜像对称【Symmetric Tree】
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,判断是否他自己的镜 ...
- POJ-2564 01背包问题
#include"cstdio" #include"cstring" #include"algorithm" using namespace ...
- 简单的RBAC用户角色权限控制
Java web项目中,无论项目是大是小,或多或少都会涉及到用户访问权限的控制,权限管理总体的设计思路就是,不该看的不看,不该做的不做!据我目前的了解,我所知道的几种实现访问权限控制的方式有: JQu ...
- POJ1365:质因数分解
Prime Land Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 3590 Accepted: 1623 Descri ...
- puppet多环境配置(puppet自动化系列2)
三.Puppet多环境部署 我们为puppetmaster建立3个环境,它们分别是开发环境(jqdev).测试环境(jqtest).生产环境(jqprd). 3.1 配置puppet.conf 在标签 ...
- 自己写的一个多应用程序多目录的Makefile
DIR_INC = ./includeDIR_SRC = ./srcDIR_OBJ = ./objDIR_BIN = ./binINCLUDES = -I${DIR_INC} -I.CC => ...
- WPF实现右键菜单
ContextMenu类就是用来做右键菜单的对象,对于任何的控件都可以进行对ContextMenu属性的操作进行设置右键菜单的功能. 下面代码就是对一个按钮添加一个WPF右键菜单的功能: < B ...