HDU 5701-中位数计数

中位数计数

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2065    Accepted Submission(s): 717


题目链接:点击打开链接


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

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

Input
多组测试数据

第一行一个数 n(n8000)

第二行 n 个数, 0 每个数 109 ,
 

Output
N 个数,依次表示第 i 个数在多少包含其的区间中是中位数。


Sample Input
5
1 2 3 4 5
 


Sample Output
1 2 3 2 1

题意:
肯定有人对题意理解的不对,就像第一次看题的我,本题是给你一组数(注意这组数不是排好序的,是无序的,题上的测试数据只是一个特例),然后让你对这组数进行遍历,找出每个数所在的区间里它是中位数的情况,比如测试数据中的4,它对应的值是2,包含4的区间有(1 2 3 4)(2 3 4)(3 4)(4)(4 5)(1 2 3 4 5)(2 3 4 5)(3 4 5) ,但是他在区间(4)和区间(3 4 5)中是中位数,还有一点就是,本题因为没有重复的数字,每个数字都是独一无二的,所以不存在以该数为中位数的偶数个数字的区间(你想啊,因为偶数个数的中位数是两个数的加和除以2,但是没有两个一样的数字,所以中位数肯定不为该数)。


分析:
我们可以定义一个神秘的数组,之所以说它神秘,是它的巧妙之处可以帮我们解决所有的问题,这个数组只要理解了,本题就过了,说说思想吧,就是先扫一下 i 右边的数,求出比它大的数的个数减去比它小的个数的差值,然后再 扫一下 i 左边的数,求出比它小的数的个数减去比它大的个数的差值,如果两个差值相等的话,是不是该数就是这个区间里的中位数了,恩恩,就这样,但代码中你必须要理解好 h 数组的含义。、



#include <stdio.h>
#include <string.h>
const int INF = 8005;
int s[INF],h[INF*2];///h数组一定要定义两倍大,以防数组下标越界

int main()
{
    int n,ans,num;
    while(scanf("%d",&n)!= EOF)
    {
        for(int i=0;i<n;i++)
            scanf("%d",&s[i]);
        for(int i=0;i<n;i++)
        {
            num=0,ans=0;///从左扫从右扫之前都要将num置0,它存的是比该数大和比该数小的数
            memset(h,0,sizeof(h));///初始化将该数组刷为0
            h[INF]++;///这个表示自身一个数的情况,也是可行的
            for(int j=i+1;j<n;j++)///从右边扫
            {
                if(s[j]>s[i])///如果大于该数,num++
                    num++;
                else///否则num--,这样就可以求出差值了
                    num--;
                h[INF+num]++;///这个带点自己理解,动手模拟
            }
            num=0;
            ans+=h[INF];///让区间里比它大的数和比它小的数相等的时候的情况累加
            for(int j=i-1;j>=0;j--)///扫左边
            {
                if(s[j]<s[i])///如果小于该数,num++
                    num++;
                else///否则num--
                    num--;
                ans+=h[INF+num];
                /**如果该数组里再扫右边得时候已经统计过,那么再遇见,就代表该区间可以
                让该数成为中位数**/
            }
            if(i<n-1)///这个是控制空格的情况
                printf("%d ",ans);
            else
                printf("%d\n",ans);
        }
    }
    return 0;
}







 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值