HDU-6070 Dirt Ratio(二分+线段树+分数规划)
(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
目录
题意:传送门
原题目描述在最下面。
求\(sum/len\)最小值。\(sum\)是一段区间内不同数字的个数,\(len\)是这段区间的长度。
思路:
首先预处理出每个数上一次出现的位置\(pre[i]\)和最后一次出现的位置\(lst[i]\)。这个操作在静态求区间内不同数的个数和动态求区间内不同数的个数都有用到。
法一:
二分答案\(mid\)。枚举序列,每加入一个数就在\(pre[i]-i\)区间加一,因为在以\(i\)为右端点的所有区间内,这么区间多了一个新数字。
对于\(sum/len\leq mid\; \rightarrow sum - len * mid \leq 0\)。我们已经处理了\(sum\),对于\(len*mid\),就在解决每次插入一个数后,在\(1-i\)区间减去\(k\)。最后查询区间最小值,如果小于\(0\)则此\(mid\)符合还可以更小。
因为我们每加入一个数后,查询的是以\(i\)为右端点的区间最小值,所以很自然的就要\(1-i\)每次减去\(k\)。这样才符合上述表达式。感觉画个图更好理解。
法二:
化简表达式为:$sum(L,R)+Lmid \leq Rmid $
\(sum\)的更新和上面一样,但是左边多了一项\(l*mid\)。
怎么办呢?解决方法就是在线段树的每个端点处的值初始化为\(l*mid\)(\(l\)是到\(1\)的距离)。
然后每此更新完后查询区间最小值\(mmin\),如果\(mmin\leq i*mid\)则此\(mid\)符合还可以更小
AC代码:
#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define mme(a,b) memset((a),(b),sizeof((a)))
using namespace std;
const int N = 1e5+7;
int n;
int lst[N],pre[N],ar[N];
double sum[N<<2],lazy[N<<2];
void push_up(int rt){
sum[rt]=min(sum[lson],sum[rson]);
}
void push_down(int rt){
if(lazy[rt]){
lazy[lson]+=lazy[rt];
lazy[rson]+=lazy[rt];
sum[lson]+=lazy[rt];
sum[rson]+=lazy[rt];
lazy[rt]=0;
}
}
void update(int L,int R,int l,int r,double c,int rt){
if(L<=l&&r<=R){
sum[rt] += c;
lazy[rt] += c;
return;
}
push_down(rt);
int mid = (l+r)>>1;
if(L<=mid) update(L,R,l,mid,c,lson);
if(R>mid) update(L,R,mid+1,r,c,rson);
push_up(rt);
}
double query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R){
return sum[rt];
}
push_down(rt);
int mid = (l+r)>>1;
double sum=n;
if(L<=mid) sum = min(sum, query(L,R,l,mid,lson));
if(R>mid) sum = min(sum, query(L,R,mid+1,r,rson));
push_up(rt);
return sum;
}
/*
1
5
1 2 1 2 3
sum/len最小值
sum/len <= mid
sum - len*mid <= 0
sum 区间不同数字的个数
len 区间长度
*/
bool ok(double e){
mme(sum,0);mme(lazy,0);
for(int i=1;i<=n;++i){
update(pre[i]+1,i,1,n,1,1);
update(1,i,1,n,-e,1);
if(query(1,i,1,n,1)<=0)return 1;
}
return false;
}
int main(){
int tim;
scanf("%d",&tim);
while(tim--){
scanf("%d",&n);
mme(lst,0);mme(pre,0);
for(int i=1;i<=n;++i){
scanf("%d",&ar[i]);
pre[i]=lst[ar[i]];
lst[ar[i]]=i;
}
double l=0,r=1,mid;
for(int i=0;i<20;++i){
mid=(l+r)/2;
if(ok(mid))r=mid;
else l=mid;
}
printf("%.5f\n", r);
}
return 0;
}
####原题目描述:
![这里写图片描述](https://img-blog.csdn.net/20180808090410937?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NTk5MDY3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
HDU-6070 Dirt Ratio(二分+线段树+分数规划)的更多相关文章
- 2017ACM暑期多校联合训练 - Team 4 1004 HDU 6070 Dirt Ratio (线段树)
题目链接 Problem Description In ACM/ICPC contest, the ''Dirt Ratio'' of a team is calculated in the foll ...
- HDU 6070 Dirt Ratio(线段树)
Dirt Ratio Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Tot ...
- hdu6070 Dirt Ratio 二分+线段树
/** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...
- HDU 6070 - Dirt Ratio | 2017 Multi-University Training Contest 4
比赛时会错题意+不知道怎么线段树维护分数- - 思路来自题解 /* HDU 6070 - Dirt Ratio [ 二分,线段树 ] | 2017 Multi-University Training ...
- K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)
大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...
- HDU 6070 Dirt Ratio(分数规划+线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意: 找出一个区间,使得(区间内不同数的个数/区间长度)的值最小,并输出该值. 思路: 因为是要求$\f ...
- hdu 6070 Dirt Ratio 线段树+二分
Dirt Ratio Time Limit: 18000/9000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Spe ...
- hdu 6070 Dirt Ratio
题 OvO http://acm.hdu.edu.cn/showproblem.php?pid=6070 (2017 Multi-University Training Contest - Team ...
- [WC2010]重建计划(长链剖分+线段树+分数规划)
看到平均值一眼分数规划,二分答案mid,边权变为w[i]-mid,看是否有长度在[L,R]的正权路径.设f[i][j]表示以i为根向下j步最长路径,用长链剖分可以优化到O(1),查询答案线段树即可,复 ...
随机推荐
- leetcode-161周赛-1250-检查好数组
题目描述: 唯一的结论是如果数组中所有数的最大公约数为 1,则存在解,否则不存在.所以只需要计算所有数最大公约数即可,时间复杂度O(nlog(m)),其中 m 为数字大小. class Solutio ...
- MySQL - primary key PK unique key,key PK index
primary key PK unique key 总结 primary key = unique + not null 主键不能为空每个字段值都不重复,unique可以为空,非空字段不重复 uniq ...
- Hive学内置条件和字符串函数
https://blog.csdn.net/skywalker_only/article/details/38752003 条件函数 下表为Hive支持的一些条件函数. 返回类型 函数名 描述 T i ...
- ecshop前台英文后台中文的设置方法
ecshop前台英文后台中文的设置方法 这里有两种方法: 第一种方法: 打开 admin/includes/init.php 文件 找到$_CFG = load_config(); 在它下面增加一行代 ...
- sql update语句
如果要更新数据库表中的记录,我们就必须使用UPDATE语句. UPDATE语句的基本语法是: UPDATE <表名> SET 字段1=值1, 字段2=值2, ... WHERE ...; ...
- PHP ftp_delete() 函数
定义和用法 ftp_delete() 函数删除 FTP 服务器上的一个文件. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE 和一个警告. 语法 ftp_delete(ftp_conne ...
- 经典排序背包——cf1203F
先把收益为正数的处理掉:策略是挨个扫,扫n遍,碰到能买的就买,然后可以得到一个更新后的r 剩下的就看做是一个背包模型:物品(a,b)表示当背包体积>a时才能装下体积为b的该物品,问最多装几个 无 ...
- Socket通信1.0
Socket通信1.0 服务器端: package page; import java.io.BufferedReader; import java.io.IOException; import ja ...
- 使用Jedis操作Redis-使用Java语言在客户端操作---set类型
原文地址:http://www.cnblogs.com/lixianyuan-org/p/9509696.html 1 //测试set数据类型 2 /** 3 * 在Redis中,我们可以将Set类型 ...
- Organizing Containers of Balls
题目 David has several containers, each with a number of balls in it. He has just enough containers to ...