bzoj 1303
中位数既然是b,那么在b左右两边比它大的数和比它小的数的个数必然要相等。
考虑把比b小的数赋值为-1,比b大的数赋值为1,b所在位置赋值为0。
做一遍前缀和,设b所在位置为w,那么问题转化为求sum[i]=sum[j](0<=i<w,w<=j<=n)的个数,开个桶来统计一下即可。
注意这个连续子序列的长度要求是奇数的,所以要分奇偶性统计。
而且C++不支持数组下标为负数,所以可以加一个N来统计。
#include<cstdio> #include<cctype> #include<algorithm> using namespace std; int read(){ char c; while(!isdigit(c=getchar())); int x=c-'0'; while(isdigit(c=getchar())) x=x*10+c-'0'; return x; } int a[100001],num[100001],sum[100001],sum1[200001][2],sum2[200001][2]; int main(){ int n=read(),b=read(),w=0; long long ans=0; for(int i=1;i<=n;i+=1){ a[i]=read(); if(b==a[i]) a[i]=0,w=i; else if(a[i]<b) a[i]=-1; else a[i]=1; sum[i]=sum[i-1]+a[i]; } for(int i=0;i<w;i+=1) sum1[sum[i]+n][i&1]++; for(int i=w;i<=n;i+=1) sum2[sum[i]+n][i&1]++; for(int i=-n;i<=n;i+=1) for(int j=0;j<=1;j+=1) ans+=(long long)sum1[i+n][j]*sum2[i+n][j^1]; printf("%lld",ans); return 0; }