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;
}

 

posted @ 2017-10-22 20:05  或是七一  阅读(76)  评论(0编辑  收藏  举报