http://acm.hdu.edu.cn/showproblem.php?pid=6070

题意:

找出一个区间,使得(区间内不同数的个数/区间长度)的值最小,并输出该值。

思路:

因为是要求$\frac{f(x)}{g(x)}$的最值,所以这是分数规划的题目,对于分数规划,是要用二分查找的方式去解决的。

就像官方题解说的,二分查找mid,二分答案mid,检验是否存在一个区间满足$\frac{size(l,r)}{(r-l+1)}<=mid$,表示l~r内不同数的个数。

先把上面的式子转化一下,,用线段树维护区间内不同数的个数,因为l*mid是固定值,所以把它也可以加进去,这样线段树就维护了区间内不等式左边的最小值。

从左到右枚举r,先是在pre[a[r]]+1~r这段区间内将区间值+1,因为这段区间内a[r]并没有出现过。更新完了之后就查询,因为线段树内记录的就是不等式左边的最小值,所以就可以返回最小值然后判断是否小于等于(r+l)*mid。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn=1e6+;
const int mod=;
const double eps=1e-; int n;
double now;
int a[maxn];
int pre[maxn];
double add[maxn<<];
double sum[maxn<<]; void PushUp(int o)
{
sum[o]=min(sum[o<<],sum[o<<|]);
} void PushDown(int o)
{
if(add[o])
{
add[o<<]+=add[o];
add[o<<|]+=add[o];
sum[o<<]+=add[o];
sum[o<<|]+=add[o];
add[o]=;
}
} void build(int l, int r, int o)
{
sum[o]=add[o]=;
if(l==r)
{
sum[o]=l*now;
return ;
}
int mid=(l+r)>>;
build(l,mid,o<<);
build(mid+,r,o<<|);
PushUp(o);
} void update(int ql, int qr, int l, int r, int x, int o)
{
if(ql<=l && qr>=r)
{
sum[o]+=x;
add[o]+=x;
return;
}
PushDown(o);
int mid=(l+r)>>;
if(mid>=ql) update(ql,qr,l,mid,x,o<<);
if(mid<qr) update(ql,qr,mid+,r,x,o<<|);
PushUp(o);
} double query(int ql, int qr, int l, int r, int o)
{
if(ql<=l && qr>=r)
{
return sum[o];
}
PushDown(o);
double ans=INF;
int mid=(l+r)>>;
if(mid>=ql) ans=min(ans,query(ql,qr,l,mid,o<<));
if(mid<qr) ans=min(ans,query(ql,qr,mid+,r,o<<|));
return ans;
} bool check()
{
memset(pre,,sizeof(pre));
build(,n,);
for(int i=;i<=n;i++)
{
double tmp=now*(i+1.0);
update(pre[a[i]]+,i,,n,,);
if(query(,i,,n,)<=tmp) return true;
pre[a[i]]=i;
}
return false;
} int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]); double l=,r=;
double ans;
while(r-l>=eps)
{
double mid = (r+l)/2.0;
now = mid;
if(check())
{
ans=mid;
r=mid-eps;
}
else l=mid+eps;
}
printf("%.9lf\n",ans);
}
return ;
}

HDU 6070 Dirt Ratio(分数规划+线段树)的更多相关文章

  1. HDU 6070 - Dirt Ratio | 2017 Multi-University Training Contest 4

    比赛时会错题意+不知道怎么线段树维护分数- - 思路来自题解 /* HDU 6070 - Dirt Ratio [ 二分,线段树 ] | 2017 Multi-University Training ...

  2. 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 ...

  3. HDU 6070 Dirt Ratio(线段树)

    Dirt Ratio Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Tot ...

  4. hdu 6070 Dirt Ratio 线段树+二分

    Dirt Ratio Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Spe ...

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

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

  6. hdu 6070 Dirt Ratio

    题 OvO http://acm.hdu.edu.cn/showproblem.php?pid=6070 (2017 Multi-University Training Contest - Team ...

  7. hdu 5274 Dylans loves tree(LCA + 线段树)

    Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  8. HDU 3074.Multiply game-区间乘法-线段树(单点更新、区间查询),上推标记取模

    Multiply game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  9. HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)

    HDU 1394 Minimum Inversion Number(线段树求最小逆序数对) ACM 题目地址:HDU 1394 Minimum Inversion Number 题意:  给一个序列由 ...

随机推荐

  1. Innodb引擎状态查看

    我们的MySQL数据库内的表一般都是Innodb表类型的. mysql>show engine  innodb status; (低版本用: show innodb status;)   === ...

  2. office 2016 install(office2016组件自定义安装激活程序) v5.9.3中文绿色版

    下载地址  http://www.ddooo.com/softdown/71741.htm#dltab office 2016 install是目前下载office2016和office2016组件最 ...

  3. 【剑指offer】从上往下打印二叉树

    一.题目: 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 二.思路: 用队列,用根节点初始化队列,然后依次从队列中取出节点,先把当前节点输出,并把左右子树分别放入队列,直到队列为空.欧了. ...

  4. MUTABLE和IMMUTABLE集合

    Scala 集合类系统地区分了可变的和不可变的集合.可变集合可以在适当的地方被更新或扩展.这意味着你可以修改,添加,移除一个集合的元素.而不可变集合类,相比之下,永远不会改变.不过,你仍然可以模拟添加 ...

  5. PAT Counting Leaves[一般]

    1004 Counting Leaves (30)(30 分) A family hierarchy is usually presented by a pedigree tree. Your job ...

  6. 4.keras实现-->生成式深度学习之用变分自编码器VAE生成图像(mnist数据集和名人头像数据集)

    变分自编码器(VAE,variatinal autoencoder)   VS    生成式对抗网络(GAN,generative adversarial network) 两者不仅适用于图像,还可以 ...

  7. testng入门教程10 TestNG参数化测试

    在TestNG的另一个有趣的功能是参数测试.在大多数情况下,你会遇到这样一个场景,业务逻辑需要一个巨大的不同数量的测试.参数测试,允许开发人员运行同样的测试,一遍又一遍使用不同的值. TestNG让你 ...

  8. (转)使用XCode6打开项目以后再用XCode5出现的问题fatal error: malformed or corrupted AST file: 'Unable to load module

    使用不同版本的XCode出现的问题: fatal error: malformed or corrupted AST file: 'Unable to load module "/Users ...

  9. Here we take a closer look at the Jordans Unveil

    Here we take a closer look at the Jordans Unveil. This Mens release is both unique and striking. The ...

  10. html05

    1.js中的对象-内置对象-外部对象-自定义对象 2.常见的内置对象有哪些?-String对象-Number对象-Boolean对象-Array对象-Math对象-Date对象-RegExp正则对象- ...