题目描述
给出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;
}