平均数 题解【二分+求逆序对】
来源:互联网 发布:淘宝客自动转换工具 编辑:程序博客网 时间:2024/05/29 07:16
【问题描述】
有一天,小A得到了一个长度为n的序列。他把这个序列的所有连续子序列都列了出来,并对每一个子序列都求了其平均值,然后他把这些平均值写在纸上,并对它们进行排序,最后他报出了第k小的平均值。你要做的就是模仿他的过程。
【输入格式】
第一行两个整数n,k,意义如题中所述。
第二行n个正整数,即为小A得到的序列。
【输出格式】
一行一个实数,表示第k小的平均值,保留到小数点后4位。
【样例输入输出】
【数据范围与约定】
对于40%的数据,n≤1000
对于100%的数据,n≤100000,k≤n*(n+1)/2,序列中的数≤10^9
【解题思路】
第k大不易直接求,我们想到二分,则原问题转变为求区间平均值小于x的区间数量。考虑把序列中的每个数减去x,则我们只需求区间和小于0的区间数量。我们对这个序列求前缀和,则区间[l,r]和小于0当且仅当Sl-1>Sr,答案即为前缀和序列S的逆序对数量,使用经典的归并排序即可解决,时间复杂度O(nlog^2n)。
对于精度问题,可以把数据*100000,最后再除以100000.0即可
【AC 代码】
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define LL long long using namespace std;const int maxn=100005;LL n,m,num,mina,maxa;LL a[maxn],s[maxn],c[maxn];LL merge(int l,int mid,int r){ int i=l,j=mid+1,k=l; LL tmp[maxn]; LL sum=0; while (i<=mid && j<=r) { if (s[i]>s[j]) { tmp[k++]=s[j++]; sum+=mid-i+1; }else { tmp[k++]=s[i++]; } } while (i<=mid) tmp[k++]=s[i++]; while (j<=r) tmp[k++]=s[j++]; for (int i=l;i<=r;i++) s[i]=tmp[i]; return sum;}LL mergesort(int l,int r){ LL tmp=0; if (l<r) { int mid=(l+r)/2; tmp+=mergesort(l,mid); tmp+=mergesort(mid+1,r); tmp+=merge(l,mid,r); } return tmp;}LL work(LL p){ s[1]=0; for (int i=1;i<=n;i++) s[i+1]=s[i]+a[i]-p; LL sum=mergesort(1,n+1);//归并求逆序对 return sum;}int main(){ scanf("%lld%lld",&n,&m); mina=100000000000005; maxa=0; for (int i=1;i<=n;i++) { scanf("%lld",&a[i]); a[i]*=100000; mina=min(mina,a[i]); maxa=max(maxa,a[i]); } LL mid,l=mina,r=maxa; while (l+1<r)//l+1<r是规范写法,其他容易WA { mid=(l+r)/2; if (work(mid)>=m) { r=mid; }else l=mid; } double ans=r*1.0/100000; printf("%.4lf\n",ans); return 0;}
【小技巧】
- 有单调性考虑二分
- 转换思想(如第k大转换为比x小的有多少,同减平均数,区间<0则找逆序对)
- 求第k大转换为枚举某个数,比它小的有多少个
- 二分判断为l+1
0 0
- 平均数 题解【二分+求逆序对】
- 【日常学习】【归并逆序对】codevs1688 求逆序对题解
- [机房练习赛] 题解 求逆序对
- 二分思想_求逆序对
- 【POJ】【P2299】【Ultra-QuickSort】【题解】【求逆序对】
- 求逆序对——Ultra-QuickSort 题解解析
- HDOJ 1394 - Minimum Inversion Number 求逆序对+二分查找
- 求逆序对
- 求逆序对
- 求逆序对
- wikioi1688 求逆序对
- POJ2299 求逆序对
- 归并求逆序对
- 求逆序对
- 求逆序对
- 【a703】求逆序对
- CodeVS1688 求逆序对
- LintCode 求逆序对
- jQuery框架的ajax理解运用
- 数组作为函数参数
- 【UOJ78】二分图最大匹配
- ubuntu下 C++ 函数创建目录
- 判断循环链表是否有环
- 平均数 题解【二分+求逆序对】
- swift地图定位(十六)poi及其他
- 一些小模板总结
- 【C#】C#实现嵌入式窗体(弹出的子窗体在父窗体内)
- 面试与简历那些事
- 取整小数
- Ubuntu 16.10 64位安装WPS
- 史上最全Java学习视频下载地址分享
- 水平/垂直滚动联动