您的位置:首页 > 编程语言 > C语言/C++

C++——NOIP模拟题——中位数

2017-04-29 14:57 435 查看


题目描述

有一个长度为 N 的数列{A1,A2,…,AN},这个 N 个数字恰好是 1..N 的一个排列。你需要统计有多少个子序列{Ai,Ai+1,…,Aj}满足:i≤j 且 j-i+1 为奇数,序列的中位数为 B。例如{5,1,3}的中位数为 3 。


输入格式

第一行包含两个正整数 N 和 B ;

第二行包含 N 个整数,第 i 个整数为 Ai。


输出格式

输出仅包含一个整数,为满足条件的子序列的个数。


样例数据 1

输入

7 4 

5 7 2 4 3 1 6
输出

4


备注

【数据范围】

对于 30% 的数据,满足:N≤100;

对于 60% 的数据,满足:N≤1000;

对于 100% 的数据,满足:N≤100000;1≤B≤N。
 

解题报告:

简单扫描。

首先,因为中位数是B且序列长度为奇数,那么这个子序列必然要包含B这个数字。接下来我们将小于B的数字看成-1,大于B的数字看成1,B看成是O。从B所在位置开始向左扫描,统计i的个数L[i];同理,向右扫描统计R[i]。最终的答案就为:∑L[i]*R[-i]。

时间效率:O(N); 空间效率:O(N)。

#include<iostream>
#include<cstdio>
int a[100001],ll[200001],rr[200001],n,b,num,ans;
inline int readint()
{
int i=0,f=1;
char ch;
for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
for(;ch>='0' && ch<='9';ch=getchar())
i=(i<<3)+(i<<1)+ch-'0';
return i*f;
}
int main()
{
register int i,j;
n=readint();
b=readint();
for(i=1;i<=n;++i)
{
a[i]=readint();
if(a[i]==b)
{
num=i;
a[i]=0;
}
else if(a[i]>b) a[i]=1;
else a[i]=-1;
}
auto int l,r;
l=r=n;
for(i=num;i>0;--i)
{
l+=a[i];
++ll[l];
}
for(i=num;i<=n;++i)
{
r+=a[i];
++rr[r];
}
int len=2*n;
for(i=0;i<=len;++i) ans+=(ll[i]*rr[len-i]);
printf("%d\n",ans);
return 0;
}
var
n,b,num,ans,i,l,r,len,p:longint;
ll,rr:array [0..200000] of longint;
a:array [0..100000] of longint;
begin
read(n,b);
for i:=1 to n do begin
read(p);
if p=b then num:=i;
if p>b then a[i]:=1;
if p<b then a[i]:=-1;

end;
l:=n;
r:=n;
for i:=num downto 1 do begin
l:=l+a[i];
ll[l]:=ll[l]+1;
end;
for i:=num to n do begin
r:=r+a[i];
rr[r]:=rr[r]+1;
end;
len:=2*n;
for i:=0 to len do ans:=ans+(ll[i]*rr[len-i]);
write(ans);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言