雕刻时光

just do it……nothing impossible
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

子串为中位数的有几个——BZOJ 1303: [CQOI2009]中位数图

Posted on 2012-02-05 14:47  huhuuu  阅读(904)  评论(0编辑  收藏  举报

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

Sample Input

7 4
5 7 2 4 3 1 6

Sample Output

4

HINT

第三个样例解释:{4}, {7,2,4}, {5,7,2,4,3}和{5,7,2,4,3,1,6}
N<=100000

 

思路:把小于中位数的数设为-1,大于的为1,等于的为0,ll=1表示该数位置在中位数的左边

sum【i】数组记录1到i数的和

统计sum[]中为0的数

如sum :1(ll) 2(ll) -1(ll) 0 -1 -1 1  0有1个

在统计sum位置左右相减为0的数又三个(方法可以通过排序做)

View Code
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;

struct data
{
int sum;
int ll;
}s[100009];

int cmp(data a,data b)
{
if(a.sum==b.sum)
return a.ll>b.ll;
else
return a.sum<b.sum;
}

int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j,temp,ri,ok=0;

s[0].sum=0;
for(i=1;i<=n;i++)
{
scanf("%d",&temp);
if(temp==m)
{
ri=i;ok=1;
}

if(ok==0)
s[i].ll=1;
else
s[i].ll=0;

if(temp>m)
temp=1;
else if(temp<m)
temp=-1;
else
temp=0;

s[i].sum=s[i-1].sum+temp;
}

int all=0;
for(i=ri;i<=n;i++)
{
if(s[i].sum==0)all++;
}

sort(&s[1],&s[n+1],cmp);
int rr=0,ll=0;
temp=s[1].sum;
for(i=1;i<=n;i++)
{
if(temp==s[i].sum)
{
if(s[i].ll)ll++;
else rr++;
}
else
{
all+=ll*rr;
ll=0;rr=0;
temp=s[i].sum;
if(s[i].ll)ll++;
else rr++;
}
}
all+=ll*rr;

printf("%d\n",all);
}
}