HDU 6070 Dirt Ratio
来源:互联网 发布:淘宝数据包里面是什么 编辑:程序博客网 时间:2024/06/10 15:35
暑假多校赛的一道题,印象深刻,今天终于补了,现在感觉也不是特别难,题意是很经典的那种问题,就是给你一个数列,问一个区间不同的个数比区间的长度的值,在这个数列里的最小值。之前搜过区间不同数的个数的查询问题,发现了一个叫主席数的东西。(不会)那么这道题应该是更难了一点,求不同数的个数还要比上区间的长度,求一个最小值。这个时候看到这种分数很容易想到分数规划,这道题就可以列个式子。x/ (r-l+1) <= mid; x(不同数的个数)肯定是要求的,转化成x-(r-l+1)mid <=0;即求这个式子的最小值,(mid是可以利用的定值),区间内不同数的个数这个问题,其实用神奇的线段树就可以解决了,还可以把式子转化为x + l*mid<= (r+1)*mid;不转化也可以做,线段树维护区间内 x+l*mid最小值,差不多就可以做出来了。总是是道不错的题。时间复杂度 n log log n
#include <algorithm>#include <bitset>#include <cassert>#include <climits>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <deque>#include <iomanip>#include <iostream>#include <map>#include <numeric>#include <queue>#include <set>#include <stack>#include <string>using namespace std;typedef long long ll;const int maxn =60150+7;int a[maxn];int pre[maxn];int lazy[maxn<<2];double sum[maxn<<2];int n;void pushdown (int i){ if(lazy[i]){ int s= lazy[i]; lazy[i*2]+= s; lazy[i*2+1]+=s; sum[i*2]+= s; sum[i*2+1]+= s; lazy[i]= 0; } return;}void build(int l,int r,int i,double mid1){ lazy[i]= 0; if(l==r){ sum[i]=mid1*l; return; } int mid= (l+r)/2; build(l,mid,i*2,mid1); build(mid+1,r,i*2+1,mid1); sum[i]= min(sum[i*2],sum[i*2+1]); return;}void update (int l,int r,int L,int R,int v,int i){ int mid=(l+r)/2; if (L<=l &&R>=r){ lazy[i]+=v; sum[i]+=v; return; } pushdown(i); if (L<=mid) update (l,mid,L,R,v,i*2); if (R>mid) update(mid+1, r, L, R, v, i*2+1); sum[i]=min (sum[i*2],sum[i*2+1]); return;}double query (int l,int r,int L,int R,int i){ if(L<=l && R>=r){ return sum[i]; } int mid=(l+r)/2; pushdown(i); double ans=0x3f3f3f3f; if(L<=mid) ans= min (ans,query(l,mid,L,R,i*2)); if (R>mid) ans =min (ans,query(mid+1,r,L,R,i*2+1) ); return ans;}double judge(double mid){ build(1,n,1,mid); int i; memset(pre,0,sizeof (pre)); for(i=1;i<=n;i++){ update(1,n,pre[a[i]]+1,i,1,1); double x = query(1,n,1,i,1); if (x<= (i+1)*mid) return 1; pre[a[i]] = i; } return 0;}int main(){ int t; int i; scanf ("%d",&t); while (t--){ memset (pre,0,sizeof(pre)); scanf("%d",&n); for (i=1;i<=n;i++){ scanf ("%d",&a[i]); } double l=0,r=1; double ans; for (i=0;i<=20;i++){ double mid=(l+r)/2; if(judge(mid))r=mid,ans=mid; else l= mid; } printf("%.10f\n",ans); } return 0;}
阅读全文
0 0
- 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 线段树 + 二分
- 【HDU 6070 Dirt Ratio】 二分 & 线段树
- HDU 6070 Dirt Ratio 二分+线段树
- HDU 6070 Dirt Ratio 线段树
- Flink入门教程--Task Lifecycle(任务的生命周期简介)
- 线程同步和线程死锁
- 如何有效的建模聚合(一)
- 集合易混点
- 使用Kettle模型清洗全国弱口令Top 1000
- HDU 6070 Dirt Ratio
- C++ DLL动态链接库的使用方法
- C++基础之C与C++的联系和不同(一)
- 梯度下降小结
- Spark性能优化指南——基础篇
- 通过父子进程完成文件io对文件的拷贝,父进程从文件开始到文件 的一半开始拷贝,子进程从文件的一半到文件末尾。
- 统计数组 arr 中值等于 item 的元素出现的次数
- JAVA 中数组的几种排序方法
- Reverse Integer