jian

【問題描述】
有N個數,隨機選擇一段區間,如果這段區間的所有數的平均值在[m,r]中則你比較厲害
求你比較厲害的概率
【輸入格式】
第一行有三個數N,m,r,含義如上描述
接下來一行有N個數代表每一個數的值
【輸出格式】
輸出一行一個分數
如果答案爲整數則直接輸出該整數即可
【樣例輸入 1】
4 2 3
3 1 2 4
【樣例輸出 1】
7/10
【樣例輸入 2】
4 1 4
3 1 2 4
【樣例輸出 2】
1
【樣例解釋】
塔外面有棵樹

【數據規模與約定】
60%的數據,1 ≤ N≤ 105
對於100%的數據,1 ≤ N ≤ 5× 105 ,0 < m≤ r≤ 100

現在是你比較強
沒想到
是個
求逆序對

以下引用

要求 區間平均值>=l&&<=r 的個數

現在我們來求區間平均值在1~r的個數和1~l(不包括l)的個數 前減後即爲所求
以求1~r爲例
(a[i]+a[i+1]+……+a[i+k-1])/k<=r
(a[i]+a[i+1]+……+a[i+k-1])<=k*r
(a[i]+a[i+1]+……+a[i+k-1])-k*r<=0
(a[i]-r)+(a[i+1]-r)+……+(a[i+k-1]-r)<=0
令c[i]=a[i]-r得到一個新數組c
即求c數組區間和<=0的個數
令s爲數組c的前綴和數組
c[i]+c[i+1]+…+c[i+k-1]<=0
s[i+k-1]-s[i]<=0
s[i+k-1]<=s[i]

i< i+k-1
s[i]>=s[i+k-1]
即求s數組逆序對數

引用結束

樹狀數組求逆序對
因爲有負數
做了一點特殊處理
使它對應一個正數

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<climits>
#include<string>
#include<cstdlib>
#include<ctime>
#define MOD 100000007
#define LL long long
using namespace std;

LL n,l,r,num[500005],s1[500005],s2[500005],b1[500005],b2[500005],pos,t1,t2,ans1,ans2,p,p1,p2,tmp,c[500005];

LL lowbit(LL x)
{
    return x&(-x);
}

LL gcd(LL a,LL b)
{
    if(!a) return b;
    else return gcd(b%a,a); 
}

LL getnum(LL x)
{
    LL ans=0,i;

    for(i=x;i>=1;i-=lowbit(i))
        ans+=c[i];

    return ans;
}

void add(LL x)
{
    LL i;
    for(i=x;i<=n;i+=lowbit(i)) c[i]++;
}

int main()
{
    LL i;

    scanf("%lld%lld%lld",&n,&l,&r);

    for(i=1;i<=n;i++)
    {
        scanf("%lld",&num[i]);

        s1[i]=num[i]-l+s1[i-1];
        b1[i]=s1[i];
        if(s1[i]<0) ans1++;

        s2[i]=num[i]-r+s2[i-1];
        b2[i]=s2[i];
        if(s2[i]<=0) ans2++;    
    }

    sort(s1+1,s1+n+1);
    sort(s2+1,s2+n+1);
    t1=unique(s1+1,s1+n+1)-s1-1;
    t2=unique(s2+1,s2+n+1)-s2-1;

    for(i=1;i<=n;i++)
    {
        pos=lower_bound(s1+1,s1+t1+1,b1[i])-s1;
        b1[i]=pos;      

        pos=lower_bound(s2+1,s2+t2+1,b2[i])-s2;
        b2[i]=pos;      
    }   

    for(i=n;i>=1;i--)
    {
        ans1+=getnum(b1[i]);
        add(b1[i]+1);
    }

    memset(c,0,sizeof(c));

    for(i=n;i>=1;i--)
    {
        ans2+=getnum(b2[i]);
        add(b2[i]); 
    }

    p1=ans2-ans1;
    p2=(n*(n+1))/2;
    tmp=gcd(p1,p2);

    p1/=tmp;
    p2/=tmp;

    if(p1==p2) printf("1");
    else printf("%lld/%lld",p1,p2);

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章