中位数计数
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1305 Accepted Submission(s): 489
Problem Description
中位数定义为所有值从小到大排序后排在正中间的那个数,如果值有偶数个,通常取最中间的两个数值的平均数作为中位数。
现在有 n 个数,每个数都是独一无二的,求出每个数在多少个包含其的区间中是中位数。
现在有 n 个数,每个数都是独一无二的,求出每个数在多少个包含其的区间中是中位数。
Input
多组测试数据
第一行一个数 n(n≤8000)
第二行 n 个数, 0≤ 每个数 ≤109 ,
第一行一个数 n(n≤8000)
第二行 n 个数, 0≤ 每个数 ≤109 ,
Output
N
个数,依次表示第
i
个数在多少包含其的区间中是中位数。
Sample Input
5 1 2 3 4 5
Sample Output
1 2 3 2 1
Source
题目大意:给你1-n一共n个数,让你枚举所有区间,找出每个区间的中位数,最后输出每个数一共当了多少次中位数
解题思路: 可以根据中位数的性质的枚举所有区间。
假设r1和r2分别是数i右边比i大的和比i小的数的个数,l1和l2分别是数i左边比数i大的和比i小的个数,假设i在这个区间中为中位数,则 r1-r2=l2-l1;
因为r2+l2=r1+l1(比i大的数等于比i小的数)所以我们可以先向右边扩展,找出所有r2-r1值并用数组记录,再向左边扩展,找出所有l1-l2,如果数组中有对应的值就在答案中相加,注意相减为0的情况要特殊处理一下。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
int a[8005];
int x[40009],n;
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
memset(x,0,sizeof x);
x[8000]=1;
int sum=0;
for(int j=i+1;j<=n;j++)
{
if(a[j]>a[i]) sum++;
else sum--;
x[8000+sum]++;
}
sum=0;
int ans=x[8000];
for(int j=i-1;j>=1;j--)
{
if(a[j]<a[i]) sum++;
else sum--;
ans+=x[8000+sum];
}
printf("%d",ans);
if(i!=n) printf(" ");
else printf("\n");
}
}
return 0;
}