中位数定义为所有值从小到大排序后排在正中间的那个数,如果值有偶数个,通常取最中间的两个数值的平均数作为中位数。
现在有 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找中位数,如果把关于每个数的区间都排列的话,实在太麻烦了。所以可以以这个数为分界线,把数列分成两部分,每一部分的数,大于他标记1,小于标记-1,本身标记为0.所以,一个包含这个数的区间和为0就算一个。又因为数组下标不能小于0,所以加个800保险一点。最后把这个数右边计数并且保存,从左边每个下标开始找,累加即可。#include <cstring> #include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <cmath> #include <map> #include <queue> #include <set> using namespace std; #define maxn 8111 int a[maxn], num[maxn], sum[maxn]; int n; int vis[maxn*2]; long long solve (int pos) { long long ans=0; sum[0]=0; num[pos]=0; for(int i=1;i<=n;i++) if(i!=pos) { if(a[i]>a[pos]) num[i]=1; else num[i]=-1; } memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) sum[i]=sum[i-1]+num[i]; for(int i=pos;i<=n;i++) vis[sum[i]+8000]++; for(int i=0;i<=pos-1;i++) ans+=vis[sum[i]+8000]; return ans; } int main () { while (scanf ("%d", &n) == 1) { for (int i = 1; i <= n; i++) scanf ("%d", &a[i]); for (int i = 1; i <= n; i++) printf ("%I64d%c", solve (i), (i == n ? '\n' : ' ')); } return 0; }