首先这题是1~n的排列,再根据后面b的取值范围,说明不存在b不出现、或出现多次的情况。
对我一个初学者来讲,虽然知道这道题运用前缀和与差分的思想,但是我不知道怎么运用这些知识点,看了大佬的题解才恍然大悟,原来可以将比b大的数定义为1,小的为-1,等于b的为0;即需求大于b的数等于小于b的数的序列。又因为包含b,说明满足奇数序列。
差分数组还原到原数组时,原数组的该位置表示的是大于b的数与小于b的数的数量差。若大于0(设为a),说明大于b的数与小于b的数抵消后还多出来a, 因此需要在右侧中找到-a,用来抵消多出来的a,实现大于b的数量等于小于b的数量。
#include<iostream>
#include<map>
#include<vector>

using namespace std;
int main(){
    int n,b;
    cin>>n>>b;
    int a=0;
    int index;//记录b出现的下标
    vector<int> v(n);//运用的差分数组
    map<int,int> M;
   
    for(int i=0;i<n;i++){
        cin>>a;
        if(a>b) v[i]=1;
        else if(a==b) {v[i]=0;index=i;}
        else v[i]=-1;
    }
    int sum=0; //用来记录到该位置时,有多少大于b的数,与多少小于b的数。当为0时,说明两者相等。当为正数(设为a)时,说明大于b的数比小于b的数多a。为-a时,说明小于b的数比大于b的数多a  
       int cnt=1;//用来记录最终答案,设为1是因为当只有一个b时,也满足答案。
    for(int i=index-1;i>=0;i--){//b的左侧序列
       if(v[i]==1) sum++;
       else if(v[i]==-1) sum--;
       if(sum==0) cnt++;//说明此处满足题意,此处大于b的数量与小于b的数量相等,b正好为中位数。
        M[sum]++;//用字典记录每个位置的数量差
    }
    sum=0;
    for(int i=index+1;i<n;i++){//右侧序列
         if(v[i]==1) sum++;
         else if(v[i]==-1) sum--;
         if(sum==0) cnt++;//与左侧序列一样         
                 cnt+=M[-1*sum];//注意右侧序列的0处可以与左侧序列的0处配对
    }
    
    cout<<cnt;
}
写的思路与代码有不正确的地方。欢迎大家的批评予指正。