【0722】T1 中位数

题目要求统计1~n排列中长度为奇数的连续子序列,其中位数为b的个数。提供了一个Pascal实现的解题思路,通过从中位数位置开始向两边查找,更新大值和小值,并记录对应数量。需要注意边界情况处理,以避免漏解。最后输出答案时需加上中位数本身的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。

样例输入:

7 4

5 7 2 4 3 1 6

样例输出:

4

解释:{4},{7,2,4},{5,7,2,4,3},{5,7,2,4,3,1,6}


先贴一发pascal渣代码……

<pre name="code" class="php">
var
	n,b,i,mark,small,big,ans:longint;
	left,right:array[-100000..100000] of longint;
	a:array[1..100000] of longint;
begin
assign(input,'median.in'); reset(input);
assign(output,'median.out'); rewrite(output);
	read(n,b);
	for i:=1 to n do
	begin
		read(a[i]);
		if a[i]=b then
			mark:=i;
	end;
	for i:=mark-1 downto 1 do
	begin
		if a[i]>b then inc(big)
		else inc(small);
	        if big=small then inc(ans);
		inc(left[big-small]);
	end;
	big:=0; small:=0;
	for i:=mark+1 to n do
	begin
		if a[i]>b then inc(big)
		else inc(small);
	        if big=small then inc(ans);
		inc(right[small-big]);
	end;
	for i:=-n to n do
		ans:=ans+left[i]*right[i];
	write(ans+1);
close(input); close(output);
end.


思路是这样的:根据数据范围n<=100000来看算法得高效一点。因为一个奇数个数的序列中位数为b,所以序列里比b大的数的个数肯定等于比b小的数的个数。假设已经找到了这样一个序列,设中位数左边比它大的数有bigleft个,比它小的数有smallleft个,中位数右边比b大的数有bigright个,比b小的有smallright个。那么bigleft+bigright=smallleft+smallright。移项得到bigleft-smallleft=smallright-bigright.

于是就可以从中位数所在位置mark开始向两端查找,每查到一个数,判断比b大还是比b小,相应地更改big和small的值,left[i]和right[i]分别记录了i=bigleft-smalleft=smallright-bigright出现的次数。注意left和right数组的下标表示的上述式子,因此下标应该是-n..n的范围。于是答案就等于所有的left[i]*right[i]之和。

然后这还不是最后答案……在查找时如果发现某一边的small=right,要inc(ans)。不然会漏解。然后最后输出答案的时候还要+1,因为中位数本身也算一个序列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值