中位数计数
Accepts: 592
Submissions: 3341
Time Limit: 12000/6000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description
中位数定义为所有值从小到大排序后排在正中间的那个数,如果值有偶数个,通常取最中间的两个数值的平均数作为中位数。
现在有nnn个数,每个数都是独一无二的,求出每个数在多少个包含其的区间中是中位数。
Input
多组测试数据
第一行一个数n(n≤8000)n(n\leq 8000)n(n≤8000)
第二行nnn个数,0≤0\leq 0≤每个数≤109\leq 10^{9}≤109,
Output
NNN个数,依次表示第iii个数在多少包含其的区间中是中位数。
Sample Input
5 1 2 3 4 5
Sample Output
1 2 3 2 1
BestCoder Contest System 2.0
Copyright © 2014-2016
HDU ACM Team
思路:分别计算每个数的左半边和右半边比当前位置上小的个数和大的个数,那么假如我们知道这个数的右半边的比这个数小的减去比这个数大的的值为d,那么如果当前的数是中位
数的话肯定有再这个区间内比当前数大的个数等于比当前数小的个数,那么我们可以知道左区间的大的数减小的数就为d,那么我们统计下左区间的d的个数 和右区间的d的个数然后乘法原理就行,还要注意加上本身,和左右右区间d=0时的个数。复杂度(O(N*N));
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<stdlib.h> 5 #include<math.h> 6 #include<string.h> 7 #include<stack> 8 using namespace std; 9 typedef struct pp 10 { 11 int x; 12 int id; 13 } ss; 14 ss ans[10000]; 15 int cnt[30000]; 16 int last[10000]; 17 int ask[10000]; 18 int cn[30000]; 19 bool cmp(pp p,pp q) 20 { 21 return p.x<q.x; 22 } 23 int main(void) 24 { 25 int i,j ,k; 26 while(scanf("%d",&k)!=EOF) 27 { memset(ask,0,sizeof(ask)); 28 for(i=0; i<k; i++) 29 { 30 scanf("%d",&ans[i].x); 31 ans[i].id=i; 32 } 33 sort(ans,ans+k,cmp); 34 int kk=ans[0].x; 35 int ak=1; 36 last[ans[0].id]=ak; 37 for(i=1; i<k; i++) 38 { 39 if(ans[i].x!=kk) 40 { 41 ak++; 42 kk=ans[i].x; 43 } 44 last[ans[i].id]=ak; 45 } 46 for(i=0; i<k; i++) 47 { 48 int l=0; 49 int r=0; 50 for(j=i-1; j>=0; j--) 51 { 52 if(last[j]>last[i]) 53 { 54 l++; 55 } 56 else r++; 57 cnt[r-l+10000]++; 58 } 59 l=0; 60 r=0; 61 for(j=i+1; j<k; j++) 62 { 63 if(last[j]>last[i]) 64 { 65 l++; 66 } 67 else r++; 68 cn[l-r+10000]++; 69 } 70 for(j=0; j<30000; j++) 71 { 72 ask[i]+=cn[j]*cnt[j]; 73 74 } 75 ask[i]+=cn[10000]; 76 ask[i]+=cnt[10000]; 77 78 memset(cnt,0,sizeof(cnt)); 79 memset(cn,0,sizeof(cn)); 80 } 81 printf("%d",ask[0]+1); 82 for(i=1; i<k; i++) 83 { 84 printf(" %d",ask[i]+1); 85 } 86 printf("\n"); 87 } 88 return 0; 89 }