题目描述
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
输入格式
第一行为两个正整数n和b,第二行为1~n的排列。
【数据规模】
对于30%的数据中,满足n≤100;
对于60%的数据中,满足n≤1000;
对于100%的数据中,满足n≤100000,1≤b≤n。
输出格式
输出一个整数,即中位数为b的连续子序列个数。
输入输出样例
输入 #1复制
7 4
5 7 2 4 3 1 6
输出 #1复制
4
我们其实并不关心数字的大小,而是只关心相对大小,因为我们选的区间长度为奇数。于是我们把大于b的当成1,b为0,小于b的为-1.
我们考虑枚举左端点,从pos-1开始到1,pos为数字b 的位置。
枚举的同时我们计算和为s,对于当前这个端点的贡献就是pos右边和为-s的个数(可以仔细思考一下)。
然后我们漏掉了pos作为左右区间的时候,和单独一个数字的时候。然后就可以了。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,b,a[N],res,pos,l[N<<1],r[N<<1],base=1e5,s;
signed main(){
cin>>n>>b;
for(int i=1;i<=n;i++) cin>>a[i],a[i]=(a[i]==b?0:(a[i]>b?1:-1));
for(int i=1;i<=n;i++) if(!a[i]) pos=i;
for(int i=pos-1;i>=1;i--) s+=a[i],l[s+base]++; s=0;
for(int i=pos+1;i<=n;i++) s+=a[i],r[s+base]++; s=0;
for(int i=pos-1;i>=1;i--) s+=a[i],res+=r[base-s];
res+=l[base]+r[base]+1;
cout<<res<<endl;
return 0;
}