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 ...
随机推荐
- Android 基础-3.0 数据存储方式
Android几种数据存储方式 文件存储 SharedPreference存储 Json解析 SQLite数据库存储 文件存储 文件存储是Android中最基本的一种存储方式,和Java中实现I/O的 ...
- Mybatis学习--Java API
学习笔记,选自Mybatis官方中文文档:http://www.mybatis.org/mybatis-3/zh/java-api.html#directoryStructure 既然你已经知道如何配 ...
- CMake简易入门
使用CMake编译 CMake工具用于生成Makefile文件.用户通过编写CMakeLists.txt文件,描述构建过程(编译.连接.测试.打包),之后通过解析该文件,生成目标平台的Makefile ...
- FEC之我见四
接上文,来详细的说明一下FEC前向纠错的具体实现: FEC_matrix是一个比较常用的算法,Vandermonde,范德蒙矩阵是法国数学家范德蒙提出的一种各列为几何级数的矩阵. 范德蒙矩阵的定义: ...
- ACM学习历程—CodeForces 601A The Two Routes(最短路)
题目链接:http://codeforces.com/problemset/problem/601/A 题目大意是有铁路和陆路两种路,而且两种方式走的交通工具不能在中途相遇. 此外,有铁路的地方肯定没 ...
- Parallel Programming-使用CancellationTokenSource调度并行运行的Task
本文主要介绍使用CancellationTokenSource调度并行运行的Task. 一.使用场景 有多个Task并行运行时,如果其中一个Task所运行的程序出现异常,我们想马上终止所有待执行的Ta ...
- bzoj 1043 下落的圆盘 —— 求圆心角、圆周长
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1043 求出每个圆没被覆盖的长度即可: 特判包含和相离的情况,注意判包含时 i 包含 j 和 ...
- java中toString() 、(String)、String.valueOf的区别
1.采用toString() 在使用时要注意,必须保证object不是null值,否则将抛出NullPointerException异常.采用这种方法时,通常派生类会覆盖Object里的toStrin ...
- TModJS:README
ylbtech-TModJS:README 1.返回顶部 1. TmodJS 项目已经停止维护,请使用更好的代替方案:art-template-loader TmodJS(原名 atc)是一个简单易用 ...
- py xrange
range(5)是列表 xrang(5)是生成器 每次调用 xrange(5),返回相应的值,比起range(5) 直接返回一个列表,性能好.