中位数计数 51Nod - 1682

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

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


Input第一行一个数n(n<=8000) 

第二行n个数,0<=每个数<=10^9OutputN个数,依次表示第i个数在多少包含其的区间中是中位数。

Sample Input

5
1 2 3 4 5
Sample Output
1 2 3 2 1

解:显然一个数要是中位数,比他大的数的个数要和比他小的数的个数相等

因为必须包括这个数,所以我们从这个数出发,分别往左往右寻找,如果比他小res--,比他大res++

比如 你先往左边 ,显然res==0时 ,ans++  ,其他的话记录  num[8000+res]++ ;

之所以+8000是因为res可能为负且最大为8000   

然后往右   res归零    ,如果比他小res--,比他大res++

不过 ans+=num[8000-res]   因为,假设你res为 1 ,那么所以左边的res为-1的情况,这个区间的值都可以使他为中位数

#include<stdio.h>
#include<string.h>
using namespace std;
int a[81111];
int num[200000];
int main()
{
   int n,ans;
   scanf("%d",&n);
   for(int i=1;i<=n;i++)
       scanf("%d",&a[i]);
  for(int i=1;i<=n;i++)
  {
  ans=1;//只有自己的情况
  memset(num,0,sizeof(num));
  num[8000]=1;//只有自己的情况也要记录
  int res=0;
  for(int j=i-1;j>=1;j--) //往左
  {
      if(a[j]>a[i])
        res++;
      else
        res--;
      num[8000+res]++;//记录状态
      if(res==0)//如果是0 是可以的
        ans++;
  }
  res=0;
  for(int j=i+1;j<=n;j++)
  {
      if(a[j]>a[i])
        res++;
      else
        res--;
      ans+=num[8000-res];//加上左边和res成相反关系的个数
  }
  if(i!=1) printf(" ");
  printf("%d",ans);
  }
 printf("\n");
}

10

10 7 4 8 2 3 1 9 6 5 

1 4 6 1 2 6 1 1 4 4 

猜你喜欢

转载自blog.csdn.net/dsaghjkye/article/details/80099714
今日推荐