zoukankan      html  css  js  c++  java
  • 一道神题

    ---恢复内容开始---

    给一个长为N的序列,对与一个区间,如果其平均值在【L,R】内,你比较厉害。

    求你比较厉害的概率。

    我只做了35分,但看了别人的神代码,我终于领会到了代码的神奇。

    思路:

      我们先求平均值在【0,R】,和【0,l)的区间个数。

      令a[i]=a[i]-R;  s[i]为a[i]的前i项的和,那么s[i]的增减就代表了 某个区间,是否是厉害区间。(增代表不是,减或者连续的减,都代表了这一段区间是厉害区间)

      然后查找逆序对的个数,因为区间平均值的 值域是很小的 对于每个值都有 很多的重复,这就用到了离散化(因为只需要知道其相对位置就行了)。

        这里用到了unque去重函数

      

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define LL long long 
    #define N 500010
    LL n,l,r;
    LL ans1,ans2,a[N],b1[N],b2[N],c[N],t,ans,tot;
    LL s1[N],s2[N];
    #define lowbit(i) (i&(-i))
    void gcd()
    {
        long long a,b,c;
        a=ans,b=tot;
        while(b)
        {
            c=a%b;
            a=b;
            b=c;
        }
        t=a;
    }
    void Add(int x)
    {
        for(int i=x;i<=n;i+=lowbit(i))        c[i]++;
    }
    LL Get(int x)
    {
        LL ans=0;
        for(int i=x;i>=1;i-=lowbit(i))
            ans+=c[i];
        return ans;
    }
    int main()
    {
        freopen("jian.in","r",stdin);
        freopen("jian.out","w",stdout);
        scanf("%d%d%d",&n,&l,&r);
        for(int i=1;i<=n;i++)    
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
        {
            s1[i]=s1[i-1]+a[i]-l;
            b1[i]=s1[i];
            if(s1[i]<0) ans1++;
            s2[i]=s2[i-1]+a[i]-r;
            b2[i]=s2[i];
            if(s2[i]<=0)    ans2++;
        }
        
        sort(s1+1,s1+1+n);
        sort(s2+1,s2+n+1);
        LL t1=unique(s1+1,s1+1+n)-s1-1;
        LL t2=unique(s2+1,s2+1+n)-s2-1;
        for(int i=1;i<=n;i++)
        {
            LL pos=lower_bound(s1+1,s1+1+t1,b1[i])-s1;
            b1[i]=pos;
            pos=lower_bound(s2+1,s2+1+t2,b2[i])-s2;
            b2[i]=pos;
        }
        for(int i=n;i>=1;i--)
        {
            ans1+=Get(b1[i]);
            Add(b1[i]+1);
        }
        memset(c,0,sizeof c);
        for(int i=n;i>=1;i--)
        {
            ans2+=Get(b2[i]);
            Add(b2[i]);
        }
        ans=ans2-ans1; 
        tot=(n+1)*n/2;
        if(ans==tot)
        {
            cout<<1;
            return 0;
        } 
        if(ans==0)
        {
            cout<<0;
            return 0;
        }
        gcd();
        printf("%lld/%lld",ans/t,tot/t);
        return 0;
    }

    ---恢复内容结束---

  • 相关阅读:
    开发avr单片机网络资源
    c语言中各种数据类型的长度
    REPEAT_BYTE(x)宏
    如何快速掌握man手册的使用
    如何获取内核代码的变更信息说明
    min宏的学习
    Spring对jdbc支持
    切入点表达式
    XML方式实现AOP编程
    注解方式实现AOP编程
  • 原文地址:https://www.cnblogs.com/CLGYPYJ/p/7632012.html
Copyright © 2011-2022 走看看