题目描述
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
输入描述:
第一行为两个正整数n和b ,第二行为1~n 的排列。
输出描述:
输出一个整数,即中位数为b的连续子序列个数。
示例1
输入
7 4
5 7 2 4 3 1 6
输出
4
备注:
对于30%的数据中,满足
n≤100;
对于60%的数据中,满足
n≤1000;
对于100%的数据中,满足
n≤100000,1≤b≤n。
#include <stdio.h>
int main(void)
{
int n, b, sum = 0, pos, cnt = 0;
scanf("%d %d", &n, &b);
int a[100010];
int c[100010] = {0};
for(int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
if(a[i] == b)
pos = i;
else if(a[i] < b)
a[i] = -1;//小于b的数为-1
else
a[i] = 1;//大于b的数为1
}
//此时数列除了pos外,其他均为1或-1,易于判断pos是否为中位数
//若包括pos在内的数列,其他项和为0,即pos为中位数
for(int i = pos-1; i >= 1; --i)//求pos左边以pos为中位数的数列个数
{
sum+=a[i];
if(sum == 0)
++cnt;
c[sum+pos]++;//依次求出与pos相连的左边数列的和,及所有和出现的个数
}
sum = 0;
for(int i = pos+1; i <= n; ++i)//求pos右边以pos为中位数的数列个数
{
sum+=a[i];
if(sum == 0)
++cnt;
cnt+=c[-sum+pos];//依次求出与pos相连的右边数列的和,
//再与上边所求的左边数列出现过的和匹配,若和为0,则加上此和出现的次数(已在上方求过)即可
}
printf("%d", cnt+1);//独自构成的数列
return 0;
}