HDU 5701中位数计数

来源:互联网 发布:乌鸦森林之谜3mac 编辑:程序博客网 时间:2024/05/20 09:24

中位数计数

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


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

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

Input
多组测试数据

第一行一个数n(n8000)

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

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

Sample Input
51 2 3 4 5
 

Sample Output
1 2 3 2 1
 
其实这个题我现在也不明白,可能是智商不够吧.....;(感觉这个题有bug,,,如果输入1,1,1,应该输出什么呢???AC的代码输出是1,1,1;但应该是这样吗???还有到底应不应该排序之后再找中位数???如果排序是应该所有数字都排序还是、找哪个区间哪个区间排序???

对每个数前后都扫一遍,是O(n^2)的复杂度(8000不算大);对第i个数后边的数,每遇到一个比他大的就加1,小的就减(用cnt记录, cnt就代表数组下标,has[mid+cnt]表示前边数大或小的个数);然后对前边的数没遇到比他大的就减1,大的就加1(如果前后cnt互为相反数,答案就加1;);
为什么互为相反数就可以呢?先看看什么是相反数:两个数符号相反,绝对值相同即为相反数,也就是说相加等于0;那么好了,前后cnt相加等于零,这也就意味着i的前后大于他的数等于小于他的数,i此时就是一个中位数;
代码:
#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <algorithm>#define MAX 8000+5using namespace std;const int mid = 8000;int num[MAX];               //记录输入的数;int has[MAX<<1];            int main(){    int n;    while(cin >> n){        for(int i=1; i<=n; i++)            cin >> num[i];        for(int i=1; i<=n; i++){            int ans=0;            int cnt=0;            memset(has, 0, sizeof(has));            has[mid]=1;                   //本身是个区间,自己就是个中位数;            for(int j=i+1; j<=n; j++){                cnt+=num[j]>num[i]?1:-1;                has[mid+cnt]++;            }            cnt=0;            ans+=has[mid];            for(int j=i-1; j>=1; j--){                cnt+=num[j]>num[i]?-1:1;                ans+=has[mid+cnt];            }            printf("%d%c", ans, i==n?'\n':' ');        }    }return 0;}






原创粉丝点击