51nod1682:中位数计数(前缀和)

基准时间限制:1 秒 空间限制:131072 KB 分值: 40  难度:4级算法题
 收藏
 关注

中位数定义为所有值从小到大排序后排在正中间的那个数,如果值有偶数个,通常取最中间的两个数值的平均数作为中位数。

现在有n个数,每个数都是独一无二的,求出每个数在多少个包含其的区间中是中位数。


Input
第一行一个数n(n<=8000)
第二行n个数,0<=每个数<=10^9
Output
N个数,依次表示第i个数在多少包含其的区间中是中位数。
Input示例
5
1 2 3 4 5
Output示例
1 2 3 2 1
Joe  (题目提供者)
C++的运行时限为:1000 ms ,空间限制为:131072 KB  示例及语言说明请按这里
思路:
Joe  (题目提供者)
考虑如何计算一个数的答案:
定义一个b数组,把所有大于自己的值定义为1,小于自己的值定义为-1,等于自己的定义为0。
如果包含这个数的区间这个数是中位数,则定义后的总和为0。
考虑前缀和,那么问题就变成了在这个数两边有多少对相等的数。
可以先把左边的数统计一下,右边的数就可以O(1)查询,时间复杂度O(n)
总时间复杂度O(N^2)。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <vector>
# define MAXN 8000

using namespace std;
int a[MAXN+1], sum[MAXN+1], num[MAXN<<1|1], res[MAXN+1];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=1; i<=n; ++i)
            scanf("%d",&a[i]);
        for(int i=1; i<=n; ++i)
        {
            sum[0] = 0;
            memset(num, 0, sizeof(num));
            int ans = 0;
            ++num[MAXN];
            for(int j=1; j<=n; ++j)
            {
                if(a[j]<a[i]) sum[j] = sum[j-1]-1;
                else if(a[j]==a[i]) sum[j] = sum[j-1];
                else sum[j] = sum[j-1]+1;
                if(j < i) ++num[sum[j]+MAXN];
                else ans += num[sum[j]+MAXN];
            }
            res[i] = ans;
        }

        for(int i=1; i<n; ++i)
            printf("%d ",res[i]);
        printf("%d\n",res[n]);
    }
    return 0;
}


转载于:https://www.cnblogs.com/junior19/p/6729919.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值