牛客:[CQOI2009]中位数图——前缀和

题目描述

给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。

输入描述:

第一行为两个正整数n和b ,第二行为1~n 的排列。

输出描述:

输出一个整数,即中位数为b的连续子序列个数。

示例1

输入

7 4
5 7 2 4 3 1 6

输出

4

备注:

对于30%的数据中,满足 n≤100n \le 100n≤100;

对于60%的数据中,满足 n≤1000n \le 1000n≤1000;

对于100%的数据中,满足 n≤100000,1≤b≤nn \le 100000,1 \le b \le nn≤100000,1≤b≤n。

题解

(1)前缀和就是从位置1到位置i这个区间内的所有的数字之和。
(2)大于中位数b的设置为1,小于b的设置为-1。
(3)cnt在中位数b左边后缀和为0时加1、右边前缀和为0时加1, 
(4)前缀和num[-c+mid]的数值等于后缀和num[-(c)+mid]的数值且不为零时,表示两边的累加和相加为0,区间和为0,b为中位数。故cnt要与num[ ]数组存储的数值相加。 

代码:

#include<bits/stdc++.h>
using namespace std;

int n,m,b,num[200005],a[100010],c=0,mid=0,cnt=1;
//中位数b是一个区间,cnt初始化为1。 
int main(){
	cin>>n>>b;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(a[i]==b)
			mid=i;//mid标志中位数的数组下标 ,此处也是位置 
		else if(a[i]>b)
			a[i]=1;
		else
			a[i]=-1;
	}
	for(int i=mid-1;i>=1;i--){
		c+=a[i];
		if(c==0)//除b之外的数列之和为0,b为中位数
			cnt++;//后缀和为0时,cnt加1 
		num[c+mid]++;///与b相连的左边数列的和,以及各和的个数 
	}
	c=0;
	for(int j=mid+1;j<=n;j++){
		c+=a[j];
		if(c==0)
			cnt++;//前缀和为0时,cnt加1 
		cnt+=num[-c+mid];//区间和为0 
	}
	cout<<cnt;
	
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值