bzoj 1303: [CQOI2009]中位数图

1303: [CQOI2009]中位数图

Time Limit: 1 Sec   Memory Limit: 162 MB
Submit: 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值