题意:
给你一个排列和一个数值k,问数组中存在多少以k为中位数且长度为奇数的连续段。

解题思路:
首先我们可以想到的是找到k的位置,然后对k左右两边取数的方式都check一遍看是否合法,时间复杂度肯定不允许;所以需要转换一下思路,因为是要求中位数,所以我们并不关心选择的序列每一位的实际大小,只需要找到序列中比k小的和比k大的一样多就行了。所以我们可以把原序列中比k大的变成1,比k小的变成-1,k位置变成0,那么如果序列合法的话,那么该子段和需要为0,所以我们只需要开一个桶来记录k左边的累加的和出现的次数和k右边累加和出现的次数,然后对出现的数进行计算即可。比如左边累加和为2,那么当右边出现和为-2时,那么这两个位置之间就是合法的。由于累加值可能为负数,所以需要把他映射到一个大于0的下标上来,当然也可以选择用map。还有一些小细节代码中有解释。

代码如下:

#include<bits/stdc++.h>
#define LL long long
#define all(x) (x).begin(),(x).end()
#define le(x) ((int)(x).size())
#define pii pair<int,int>
#define PII pair<LL,LL>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define db printf("Here!\n");
using namespace std;
const double eps=1e-8;
const double Pi=4.0*atan(1.0);
const LL inf=1e14+10;
const int N=2e5+5;
const int M=2e6+5;
const int mod=1e9+7;
int n,m,k,t,T,len,op,x,y,z;
int a[N],cnt[M];
void solve(){
    scanf("%d%d",&n,&k);
    LL ans=0,pos,now=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        if(x==k)pos=i;
        else a[i]=(x>k?1:-1);
    }
    for(int i=pos-1;i>=1;i--){//统计左边累加出线的次数
        now+=a[i];
        if(!now)ans++;//累加和等于0时说明不需要右边的,可以直接加1
        cnt[now+N]++;
    }
    now=0;
    for(int i=pos+1;i<=n;i++){
        now+=a[i];
        if(now==0)ans++;//与上面同理
        ans+=cnt[-now+N];//该位置的值可以与左边累加和出现-now的所有位置构成合法序列
    }
    printf("%lld\n",ans+1);//别忘了k自己也可以构成一个
}
int main(){
    //int o;scanf("%d",&o);
    //while(o--){
        solve();
    //}
    return 0;
}