原题链接:https://vjudge.net/problem/1663377/origin
题解:
先看如何判断一个数是否为中位数:
如果这个数m,比它大的和比它小的数是一样多的,那么它就是中位数。
在这个题里,n个数是不重复而且连续的,那么以m为中位数的子序列必定含有m,
所以我们先找到m的位置,立个flag,从flag右边开始枚举,如果枚举的数大于m,cnt就加1,否则就减1;
建个数组vis来存大于m与小于m的数之差。
再枚举左边的数,如果枚举的数大于m,cnt减一,小于m,cnt+1,这样当左右两边综合考虑时,当大于m与小于m的数一样多时,vis里面的数就是以m为中位数的区间个数。
具体见代码注释。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int maxn=5e5+10;
int a[maxn*2];
int vis[maxn*2];
int main()
{
int m,n,flag,cnt=0;
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>a[i];
if(a[i]==m)
{
flag=i;
}
}
for(int i=flag;i<n;i++)//往右边开始枚举
{
if(a[i]>m)
{
cnt++;
}
if(a[i]<m)
{
cnt--;
}
vis[maxn+cnt]++;//因为cnt可能是负数,所以加个maxn防止数组索引出现负数
}
long long int sum=0;
cnt=0;
for(int i=flag;i>=0;i--)
{
if(a[i]>m)
{
cnt--;
}
if(a[i]<m)
{
cnt++;
}
sum+=vis[maxn+cnt];
sum+=vis[maxn+cnt+1];//偶数就加一,不懂的话,具体过程可自行模拟一下就很容易理解
}
cout<<sum<<endl;
return 0;
}