[bzoj1303][CQOI2009]中位数图

来自FallDream的博客,未经允许,请勿转载,谢谢。


 

给定一个n个数排列,求有多少段长度为奇数的区间,中位数是b. n<=100000 时间限制0.1s

我一开始没看到排列,想着怎么还能O(n)做的啊??然后突然发现......

那就很简单啦,把大于b的数看作1,小于的看作-1,从b往两边前缀和,答案就是两边前缀和L[x],R[y]互为相反数的(x,y)的对数。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define MN 200000
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int n,b,p,x=0,ans=0;
int a[MN+5],L[MN+5];

int main()
{
    x=n=read();b=read();
    for(register int i=1;i<=n;++i)
    {
        a[i]=read();
        if(a[i]>b)a[i]=1;
        else if(a[i]<b)a[i]=-1;
        else {a[i]=0;p=i;}
    }
    for(register int i=p-1;i;--i)
    {
        x+=a[i];
        ++L[x];
    }
    x=n;ans=++L[n];
    for(register int i=p+1;i<=n;++i)
        x-=a[i],ans+=L[x];
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2017-04-03 22:41  FallDream  阅读(274)  评论(0编辑  收藏  举报