4.中位数
(median.pas/c/cpp)
【问题描述】
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
【输入】
第一行为两个正整数n和b ,第二行为1~n 的排列。
【输出】
输出一个整数,即中位数为b的连续子序列个数。
【样例输入】
7 4
5 7 2 4 3 1 6
【样例输出】
4
【样例解释】
分别是子序列{4},{7,2,4},{5,7,2,4,3},{5,7,2,4,3,1,6}
【数据范围】
N<=100000
其实还是蛮好上手的一道题,显然我们符合要求的序列:
1、一定包含我们的中位数,
2、而且序列内大于中位数的个数等于小于中位数的个数相等(中位数定义可知=。=)
3、序列长度为奇数
我们设中位数在序列中的位置为t
对于1~t-1
a[i],a[i+1],a[i+2]......,a[t-1]
我们用l_min[i]记录a[i]~a[t] 中比中位数小的个数,用l_max[i]记录a[i]~a[t]中比中位数大的个数
同理,对于a[t+1],a[t+2],...,a[n]
我们用r_min[j]记录a[t]~a[n]中比中位数小的个数,用r_max[j]记录a[t]~a[n]中比中位数大的个数
那么满足条件的序列a[i]~a[j]一定有
1.i<=t<=j
2.j-i>=2
3.l_min[i]+r_min[j]=l_max[i]+r_max[j] (i<t<j)
l_min[i]=l_max[j](i<t=j)
r_min[i]=r_max[j](t=i<j)
然后分水岭来了=w=
方法一:处理完后枚举1~t-1,t+1~n,满足上述三条要求的加答案,期望得分70
AC方法:由于两边同时处理会TLE,所以我们考虑一边的min和max一起处理,
于是l_min[i]+r_min[j]=l_max[i]+r_max[j] 变形(看好了我要变了!!) l_min[i]-l_max[i]=r_max[j]-r_min[j]
即 l_min[i]-l_max[i]=-(r_min[j]-r_max[j] )
那么我们只需要处理出 l_min[i]-l_max[i]=k的序列个数fl[k]和 r_min[j]-r_max[j]=k的序列个数fr[k]
然后ans:=Σfl[k]*fr[-k] (-n<=k<=n),最坏时间复杂度O(n),完美=w=
PS:考试的时候由于我是从中位数的位置向两边同时去更新,导致一边更新完成时另一边还没有完成更新,听取wa声一片QAQ
在更新数值的时候,如果是从中间向两端同时更新,在更新后要判断两边是否全部完成更新,不要留下有一边只更新一部分的情况
注意对不存在中位数m的特判
代码
var
n,m,t,ans :longint;
a,lmin,lmax,rmin,rmax:array[0..100010] of longint;
t1,t2 :array[-100005..100005] of longint;
i,j :longint;
begin
read(n,m);
for i:=1 to n do read(a[i]);
for i:=1 to n do if a[i]=m then break;
t:=i;
lmin[t]:=0;lmax[t]:=0;rmin[t]:=0;rmax[t]:=0;
//
for i:=t-1 downto 1 do
begin
lmin[i]:=lmin[i+1];
lmax[i]:=lmax[i+1];
if a[i]<m then inc(lmin[i]) else inc(lmax[i]);
if lmin[i]=lmax[i] then inc(ans);
end;
//
for i:=t+1 to n do
begin
rmax[i]:=rmax[i-1];
rmin[i]:=rmin[i-1];
if a[i]>m then inc(rmax[i]) else inc(rmin[i]);
if rmax[i]=rmin[i] then inc(ans);
end;
//
for i:=1 to t-1 do inc(t1[lmin[i]-lmax[i]]);
for i:=t+1 to n do inc(t2[rmin[i]-rmax[i]]);
for i:=-n to n do inc(ans,t1[i]*t2[-i]);
if t=0 then writeln(0) else writeln(ans+1);
end.
附上一个中位数的性质=w=: 有一列数X1,X2,X3,...,Xn,
f(x)=|X1-x|+|X2-x|+|X3-x|+...+|Xn-x|,当x=数列中位数时,f(x)最小
——by Eirlys
转载请注明出处=w=