HDU 6070 Dirt Ratio(二分+线段树 17多校第四场)
来源:互联网 发布:苹果mac系统os 编辑:程序博客网 时间:2024/05/29 11:43
- 题目大意
给定一个序列a[],让你求出一个子区间内不同元素个数除以区间长度的最小的一个值。
n≤6∗104 ,答案精度不高于10−4 分析
题目要求的是:
min{dif[l][r]r−l+1}(1≤l≤r≤n,dif[l][r]表示区间[l,r]内不同元素的个数)
最暴力的方法通过两层循环来枚举这个区间,外层循环是左端点,内层循环是右端点。
类似于CF 833B,我们可以用一个数组pre[x] 保存在x 前面最近的和a[x] 相等的数的下标,这样我们可以通过O(1) 的复杂度从dif[l][r] 推得dif[l][r+1]
同样类似于CF 833B,这样的O(n2) 的复杂度还是会超时
我们尝试去用一种数据结构来维护这个区间最小值
我们可以O(1) 的复杂度从dif[l][r] 推得dif[l][r+1] ,那么我们可以通过线段树以O(logn) 的复杂度从dif[1...l][r] 推得dif[1...l][r+1] ,但是这个区间信息是一个带除法运算的表达式我们很难对这个分母进行区间的更新操作
如果我们能够将除法运算转化成加法运算。
。
如果我们想到了二分,
min{dif[l][r]r−l+1}≤mid 是否成立
变换一下也就是min{dif[l][r]+l∗mid−mid}≤r∗mid 是否成立
这样我们就能够对表达式dif[l][r]+l∗mid−mid 通过线段树来进行区间更新和查询操作了代码
#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<map>#include<algorithm>#include<set>#include<stack>using namespace std;const double INF=999999.0;const long long int MOD=998244353;const int MAXN=60005;int T;int n;int a[MAXN];int pre[MAXN];int pos[MAXN];double tree[MAXN*4];double lazy[MAXN*4];void PushUp(int rt)//将延迟标记上推{ tree[rt]=min(tree[rt*2],tree[rt*2+1]);}void PushDown(int rt){ lazy[rt*2]+=lazy[rt]; lazy[rt*2+1]+=lazy[rt]; tree[rt*2]+=lazy[rt]; tree[rt*2+1]+=lazy[rt]; lazy[rt]=0; return ;}void Build(double x,int l,int r,int rt){ lazy[rt]=0; if(l==r) { tree[rt]=(double)l*x-x; return ; } int m=(l+r)/2; Build(x,l,m,rt*2); Build(x,m+1,r,rt*2+1); PushUp(rt);}void Update(int L,int R,int l,int r,int rt){ if(l>=L && r<=R) { lazy[rt]+=1; tree[rt]+=1; return ; } int m=(l+r)/2; PushDown(rt); if(L<=m)Update(L,R,l,m,rt*2); if(R>m)Update(L,R,m+1,r,rt*2+1); PushUp(rt);}double Query(int L,int R,int l,int r,int rt){ if(l>=L &&r<=R) { return tree[rt]; } double ans=INF; PushDown(rt); int m=(l+r)/2; if(L<=m)ans=min(ans,Query(L,R,l,m,rt*2)); if(R>m)ans=min(ans,Query(L,R,m+1,r,rt*2+1)); PushUp(rt); return ans;}bool Check(double x)//判断x作为答案是否可行{ Build(x,1,n,1); double minm=INF; for(int i=1;i<=n;i++) { Update(pre[i]+1,i,1,n,1); if(Query(1,i,1,n,1)<=(double)i*x){return 1;} } return 0;}void Work(){ double l=0; double r=1.0; double m; while(r-l>0.0000001) { m=(l+r)/2; if(Check(m))r=m; else l=m; } cout<<l<<endl;}int main(){ scanf("%d",&T); while(T--) { memset(pos,0,sizeof(pos)); memset(pre,0,sizeof(pre)); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); pre[i]=pos[a[i]]; pos[a[i]]=i; } Work(); } return 0;}/*151 2 1 2 3*/
阅读全文
0 0
- HDU 6070 Dirt Ratio(二分+线段树 17多校第四场)
- HDU 6070 Dirt Ratio(二分+线段树 17多校第四场)
- HDU 6070-Dirt Ratio(多校训练第四场->二分+线段树)
- 多校第四场1004 HDU 6070 Dirt Ratio
- HDU 6070 Dirt Ratio 线段树 二分
- HDU 6070 Dirt Ratio [二分+线段树]
- hdu 6070 Dirt Ratio 二分,线段树
- hdu 6070 Dirt Ratio(线段树+二分)
- hdu 6070 Dirt Ratio二分 线段树
- HDU 6070 Dirt Ratio 线段树 + 二分
- 【HDU 6070 Dirt Ratio】 二分 & 线段树
- HDU 6070 Dirt Ratio 二分+线段树
- HDU 6070 Dirt Ratio(二分+线段树)
- HDU-6070 Dirt Ratio(二分+线段树+分数规划)
- hdu 6070 Dirt Ratio(二分+线段树维护区间最小值)
- HDU 6070 Dirt Ratio(二分+线段树)
- hdu 6070 Dirt Ratio(线段树+二分答案)
- HDU 6070 Dirt Ratio (线段树+二分)
- 完美的数字
- 一个配置导致的HTTP(TCP)连接超时
- 如何生成密钥,私钥,签名
- ORA-12505
- 算法学习之旅,初级篇(4)--哈密尔顿距离
- HDU 6070 Dirt Ratio(二分+线段树 17多校第四场)
- docker容器和数据库数据分离
- 关于bootstrap-treeview数型结构的转化及使用、增删改等操作
- MD5对密码进行加密,用Apache codec 替换Sun内部API sun.misc.BASE64Encoder
- shell编程之结构化命令if-then
- 4步教你开发风控评分模型
- 1222 Wolf and Rabbit
- IIS配置支持跨域请求
- hadoop MapReduce集群模式调整匹配及shell脚本处理