1303: [CQOI2009]中位数图
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2747 Solved: 1704
[ Submit][ Status][ Discuss]
Description
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
Input
第一行为两个正整数n和b ,第二行为1~n 的排列。
Output
输出一个整数,即中位数为b的连续子序列个数。
Sample Input
7 4
5 7 2 4 3 1 6
Sample Output
4
这题非常单纯,长度必须为奇数,而且必须是1-n的排列,那么问题就很简单了
统计前缀和,sum[i]==k表示前i个数里大于d的数与小于d的数差为k
还没遍历到d之前,更新flag[k],flag[k]==m表示总共有m个前缀和sum[]==k,
(因为k的范围是[-n, n],数组下标不能为负,所以可以整体+n)
遍历到d之后,对于当前sum[i],所有以第i个元素为结尾中位数为d的连续子序列个数就为flag[sum[i]]!
最后答案就是∑flag[sum[i]] (d所在位置<=i<=n)
#include<stdio.h>
#include<string.h>
int a[100005], sum[100005], flag[200010];
int main(void)
{
int n, d, i, ans, ok;
while(scanf("%d%d", &n, &d)!=EOF)
{
ans = ok = 0;
memset(flag, 0, sizeof(flag));
flag[n] = 1;
for(i=1;i<=n;i++)
{
scanf("%d", &a[i]);
if(a[i]>d) sum[i] = sum[i-1]+1;
if(a[i]==d) sum[i] = sum[i-1], ok = 1;
if(a[i]<d) sum[i] = sum[i-1]-1;
if(ok==1) ans += flag[sum[i]+n];
if(ok==0) flag[sum[i]+n]++;
}
printf("%d\n", ans);
}
return 0;
}