[USACO11NOV]Above the Median G

题目

Description

农夫约翰把他的N(1<=N<=1e5)奶牛排在一排来衡量他们的高度,牛i有:高度H_I(1<=H_I<=1e9)纳米–因为FJ认为他需要精确测量!他想选择一些连续的奶牛拍一张照片发给牛摄影大赛。大赛有一个很奇怪的规则,对所有提交的照片:照片有效当且仅当,它描绘了一群中位身高至少大于一定的阈值X(1<=x<=1e9)的奶牛。中位身高定义为:有n头奶牛按从小到大顺序排好,第[(1+n)/2](取上限)头奶牛的身高。例如{7,3,2,6}的中位数是6,和{5,4,8}的中位数是5。FJ想知道他有多少种选择。

Input

*第1行:两个用空格隔开的整数:N和X  
*第2 .. N 1:第i行1包含单个整数H_I。

Output

*第1行:选择的个数,注意,该数可能超出32位整数的存储范围。

Sample Input

4 6 
10 
5 
6 
2 

Sample Output

  7 

Hint

有10个可能选择。其中,只有7 个的中位数大于6。它们是{10},{6},{10,5},{5,6},{6,2},{10, 5,6},{1 
0,5,6,2}


思路

如果不知道怎么求a前面小于a的个数

https://www.cnblogs.com/wzx-RS-STHN/p/13193271.html

 

首先令小于X的数为-1,大于X的数为1;

再定义一个s[i]前缀和数组表示1-i中-1和1的和;

如果s[i]==0,那么说明1-i中大于X的数和小于X的数 ,他们的数量都是一样的;

如果s[i]>0,那么说明1-i中大于X的数比小于X的数 要大;

也说明1-i中的中位数是大于X的;

举个栗子:

4 6

1 2 8 6

s[1]=-1,s[2]=-2,s[3]=-1,s[4]=0;

s[4]>=0,所以1-4中的中位数6,是大于X的;

所以我们只需要求出每个s[j]-s[i]是否大于等于0就好了;

for(ll i=1;i<=n;i++)
for(ll j=i;j<=n;j++)
    if(s[j]-s[i]>=0)
        ans++;

这段代码可以转化为求比s[j]小的s[i]有多少个;

这样很明显就可以用树状数组优化了

for(ll i=1;i<=n;i++)
{
    ll x=findout(s[i]);//查找比s[i]并且在s[i]前面的数有多少个
    ans+=x;
    insert(s[i],1);//插入s[i];
}

 

需要注意的问题是要s[1]=0,因为s[i]-s[1]相当于1-i的前缀和;

如果s[1]不从0开始,那么会少统计1-i的前缀和;

 

知道这些还不够,你还是不能AC

那么还要注意什么问题呢;

我们加入树状数组的s[i]可能为0或负数,然鹅树状数组是不能出现0或负数的;

所以每次加入的s[i]要加上一个N;

 

代码

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline ll read()
{
    ll a=0,ha=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') ha=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*ha;
}
ll n,m,sum[1000010];
ll a1[1000010],s[1000010];
struct oh
{
    ll v,num;
}a[1000010];
inline ll lowbit(ll x)
{
    return x&(-x);
}
inline void insert(ll x,ll y)
{
    while(x<=2*n)//      注意!!!注意!!!!! 
    {
        sum[x]+=y;
        x+=lowbit(x);
    }
}
inline ll findout(ll x)
{
    ll ans=0;
    while(x)
    {
        ans+=sum[x];
        x-=lowbit(x);
    }
    return ans;
}
int main()
{//具体请看上面的思路 
    n=read();m=read();
    for(ll i=1;i<=n;i++)
    {
        ll x=read();
        if(x>=m)
            a1[i]=1;
        else
            a1[i]=-1;
    } 
    for(ll i=1;i<=n;i++)
        s[i]=s[i-1]+a1[i];//把前缀和统计出来 
    insert(n,1);
    ll ans=0;
    for(ll i=1;i<=n;i++)
    {//我们加入树状数组的s[i]可能为0或负数,然鹅树状数组是不能出现0或负数的;
     //所以每次加入的s[i]要加上一个N;
        ll x=findout(s[i]+n);//查找比s[i]并且在s[i]前面的数有多少个
        ans+=x;
        insert(s[i]+n,1);//插入s[i];
    }
    printf("%lld\n",ans);
}

 

原文链接: https://www.cnblogs.com/wzx-RS-STHN/p/13236982.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    [USACO11NOV]Above the Median G

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/362731

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午2:32
下一篇 2023年3月2日 下午2:33

相关推荐