51nod1711 平均数

来源:互联网 发布:原始股 购买 知乎 编辑:程序博客网 时间:2024/05/23 18:41

题目

LYK有一个长度为n的序列a。
他最近在研究平均数。
他甚至想知道所有区间的平均数,但是区间数目实在太多了。
为了方便起见,你只要告诉他所有区间(n*(n+1)/2个区间)中第k大的平均数就行了。
Input
第一行两个数n,k(1<=n<=100000,1<=k<=n*(n+1)/2)。
接下来一行n个数表示LYK的区间(1<=ai<=100000)。
Output
一行表示第k大的平均数,误差不超过1e-4就算正确。
Input示例
5 3
1 2 3 4 5
Output示例
4.000

题解

首先看到这种平均数我们很套路的想到二分
我们先看一下在什么时候(i,j)有贡献,设当前二分值为mid
sum[j]sum[i]ji>mid时(i,j)的平均数就比mid大,此时有贡献
那么我们可以移一下项,得:sum[i]midi<sum[j]midj
那么我们预处理这个东西然后搞一下二维偏序就好了
注意0也要加进去

贴代码

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#define db double#define ll long longusing namespace std;const int maxn=10005,md=100000007;struct node{    db x,y,z;}a[maxn],b[maxn];int i,j;ll p,ans,c,ge,nt,k,n;ll cc[maxn];int cmp(node x,node y){    return x.z<y.z;}bool check(node x,node y){    return x.x*y.y>x.y*y.x;}int main(){    freopen("forgive.in","r",stdin);    freopen("forgive.out","w",stdout);    scanf("%d%d",&n,&p);    for (i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);    cc[0]=1;    c=(p*p)%md;    for (i=1;i<=n;i++) cc[i]=(cc[i-1]*(1-p+md))% md;    ans=3*(n*p+cc[n])-3;    ans=ans%md;    nt=n-1;    for (i=1;i<=n;i++){        for (j=1;j<=n;j++){            b[j].x=a[j].x-a[i].x;            b[j].y=a[j].y-a[i].y;            b[j].z=atan2(b[j].y,b[j].x);            if (i==j) b[i].z=21474844;        }        sort(b+1,b+n+1,cmp);        k=1;        ge=0;        for (j=1;j<=nt;j++){            while (check(b[j],b[k%nt+1])) {                ge++;                k=k%nt+1;            }            ans=(ans-(cc[n-ge-2]*c)%md+md)% md;            if (ge) ge--; else k=k%nt+1;        }    }    printf("%d",ans);    return 0;}
0 0
原创粉丝点击