Description
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
Input
第一行为两个正整数n和b ,第二行为1~n 的排列。
Output
输出一个整数,即中位数为b的连续子序列个数。
Sample Input
样例输入1:
5 4
1 2 3 4 5
样例输入2:
6 3
1 2 4 5 6 3
样例输入3:
7 4
5 7 2 4 3 1 6
Sample Output
样例输出1:
2
样例输出2:
1
样例输出3:
4
Hint
第三个样例解释:{4}, {7,2,4}, {5,7,2,4,3}和{5,7,2,4,3,1,6}。
分析: 这道题硬算显然会超时,所以我们要考虑相对简便的算法。
在区间内取中位数,可以转化成比中位数大的数的个数与比中位数小的数的个数的差的绝对值。
所以我们先锁定中位数pos的位置,再将中位数左边的数分为一部分,中位数右边的数分成另一部分,然后分别求出1 - pos, pos - N段的相对数量。、
所以此题就转化为了寻找一段区间,使得这段区间的相对数量为0.
其中比中位数大的数设为1,比中位数小的数设为-1.
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100006;
int a[MAXN], cnt[2 * MAXN], N, K, pos, s, ans;
int main()
{
scanf("%d%d", &N, &K);
for (int i = 1; i <= N; i++)
{
scanf("%d", &a[i]);
if (a[i] == K) pos = i;
}
for (int i = pos; i >= 1; i--)
{
if (a[i] > K) s++;
else if (a[i] < K) s--;
if (s == 0) ans++;
cnt[s + N]++;
}
s = 0;
for (int i = pos + 1; i <= N; i++)
{
if (a[i] > K) s++;
else if (a[i] < K) s--;
ans += cnt[N - s];
}
printf("%d\n", ans);
return 0;
}