DestinHistoire

 

BZOJ-1303 [CQOI2009]中位数图(前缀和+计数)

题目描述

  给出 \(1,2,\cdots,n(n\leq 10^5)\) 的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是 \(b\)。中位数是指把所有元素从小到大排列后,位于中间的数。

分析

  读入的时候把大于 \(b\) 的数赋值为 \(1\),小于 \(b\) 的数赋值为 \(-1\)\(b\) 的下标设为 \(pos\)。设 \(l[i]\)\(pos\) 左边的后缀和为 \(i\) 的后缀数目,\(r[i]\)\(pos\) 右边的前缀和为 \(i\) 的前缀数目。枚举 \(-10^5\leq x\leq 10^5\)\(l[x]\) 可以与 \(r[-x]\) 匹配,方案数为 \(l[x]\times r[-x]\)。答案即为 \(\displaystyle\sum_{i=-10^5}^{10^5}l[i]\times r[-i]\)

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int a[N+10],l[4*N+10],r[4*N+10];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main()
{
    int n,b,pos;
    cin>>n>>b;
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        if(a[i]>b)
            a[i]=1;
        else if(a[i]==b)
            pos=i;
        else
            a[i]=-1;
    }
    l[N+0]=r[N+0]=1;
    int sum=0;
    for(int i=pos-1;i>=1;i--)
    {
        sum=sum+a[i];
        l[N+sum]++;
    }
    sum=0;
    for(int i=pos+1;i<=n;i++)
    {
        sum=sum+a[i];
        r[N+sum]++;
    }
    long long ans=0;
    for(int i=0;i<=N+100000;i++)
        ans=ans+l[i]*r[2*N-i];
    cout<<ans<<endl;
    return 0;
}

posted on 2020-12-07 12:14  DestinHistoire  阅读(53)  评论(0编辑  收藏  举报

导航