一个朴素的想法是把大于的数规约成,小于的数规约成,那么中位数为就是区间的所有的和为。
而给出的数列是一个排列,那么只有唯一的位置,从这个位置向两边求和,就可以找出题目要求的区间。
于是整个区间的和就变成了,其中分别是左端和右端的子串和。
把判断等式变成,发现这个可以直接找对应关系。
所以先把右边每个位置的和求出来,丢进一个,然后对左边依次求和,并且在中找到对应的,计入答案即可。
记得开。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<map>
#define MAXN 100010
using namespace std;
int n,m,pos,suml=0,sumr=0,val[MAXN];
long long ans=0;
map<int,int> a;
char tp[100000],*p1=tp,*p2=tp;
inline char get_char(){
return p1==p2&&(p2=(p1=tp)+fread(tp,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=get_char();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=get_char();}
return date*w;
}
void work(){
for(int i=pos;i<=n;i++){
if(val[i]<m)sumr--;
if(val[i]>m)sumr++;
a[sumr]++;
}
for(int i=pos;i>=1;i--){
if(val[i]<m)suml--;
if(val[i]>m)suml++;
ans+=a[-suml];
}
printf("%lld\n",ans);
}
void init(){
n=read();m=read();
for(int i=1;i<=n;i++){
val[i]=read();
if(val[i]==m)pos=i;
}
}
int main(){
init();
work();
return 0;
}