题目描述
给出1-n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
输入描述:
第一行为两个正整数n和b ,第二行为1~n 的排列。
输出描述:
输出一个整数,即中位数为b的连续子序列个数。

思路
只在乎和b的相对大小,而不在乎具体多少,所以我们可以把大于b的值都定为1,小于b的值都为-1,这样的话,问题转化为,求有多少个区间的和为0,并且包含数字b的位置。
那么我们找出b的位置,然后从b的位置往前计算和,存入数组中,然后往右遍历计算和,看前面是不是已经存过了,存过了就加起来前面存的个数即可。
注意b单独一个数字也是一个区间,所以算完b前面的数字和后,满足的区间有1(b的位置本身)+f[0](前面的和为0的个数),然后把f[0]++,即先算出来b的位置作为区间右端点满足的个数,然后把b的位置加入区间左端点中。

注意和为负,所以开两个数组分别存正负的和

// 1 1 -1 0 -1 -1 1
#include<bits/stdc++.h>
using namespace std;
#define int long long
int pos;
int a[1<<17];
int z[1<<17],f[1<<17];
signed main(){
    int n,b;cin>>n>>b;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]>b) a[i]=1;
        else if(a[i]<b) a[i]=-1;
        else a[i]=0,pos=i;
    }
    int ans=0;
    for(int i=pos-1;i;i--){
        ans+=a[i];
        if(ans>0) z[ans]++;
        else f[-ans]++;
    }
    ans=0;
    int cnt=1+f[0];
    f[0]++;
    for(int i=pos+1;i<=n;i++){
        ans+=a[i];
        if(ans>=0) cnt+=f[ans];
        else cnt+=z[-ans];
    }
    if(b>n) cnt=0;
    cout<<cnt;
    return 0;
}