zoukankan      html  css  js  c++  java
  • [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
    ",ans);
    }
  • 相关阅读:
    fpm 打包教程
    fpm 打包工具安装调试
    kubernetes 容器挂载 ceph rbd 卷的平滑扩容方法
    kubernetes ceph-rbd挂载步骤 类型PersistentVolume
    ceph 块设备
    kubernetes 外部访问集群暴露端口服务
    kubernetes job的原理
    国内GIT托管服务
    Euclidean Space
    Struct Member Default Value
  • 原文地址:https://www.cnblogs.com/wzx-RS-STHN/p/13236982.html
Copyright © 2011-2022 走看看