有一個長度爲N的數列{A1,A2,...,AN},這N個數字剛好是1...N的一個排列。你須要求出這個序列有多少個子序列{Ai,Ai+1,...,Aj}知足:數組
一、i≤j且j-i+1爲奇數。spa
二、這個序列的中位數爲B。code
例如{5,1,3}的中位數爲3。blog
輸入文件第一行包含兩個正整數N和B,知足1≤N≤100000且1≤B≤N。io
第二行包含N個整數Ai。class
輸出文件僅包含一個整數,爲知足條件的子序列個數。原理
7 4 di
5 7 2 4 3 1 6文件
4co
若是B是一個序列的中位數,那麼這個序列中比B大的數的個數和比B小數的個數相等。事實上,咱們不須要知道這些數的具體數值,只要知道這些數和B的大小關係就夠了。
把比B大的數記爲1,比B小的數記爲-1,分別計算以B爲右端點的後綴和lsum和以B爲左端點的前綴和rsum,對於任意一個子序列的左端點l和右端點r,當lsum[l]+rsum[r]==0時知足條件。
設lnum[i]表示lsum[j]==i的lsum的個數,rnum[i]表示rsum[j]==i的rsum的個數,根據乘法原理,知足條件的子序列的個數爲∑lnum[i]*rnum[-i]
注意到lnum和rnum的下標可能爲負,數組總體右移。
1 #include <cstdio> 2 int n,B,a[100005],lsum[100005],rsum[100005],lnum[200005],rnum[200005],ans; 3 int main() 4 { 5 int i,j,p,l,r; 6 scanf("%d%d",&n,&B); 7 for (i=1;i<=n;i++) 8 scanf("%d",&a[i]); 9 for (p=1;p<=n && a[p]!=B;p++); 10 lnum[n]=rnum[n]=1; 11 for (i=p-1;i>=1;i--) 12 lsum[i]=a[i]>B?1:-1, 13 lsum[i]+=lsum[i+1], 14 lnum[lsum[i]+n]++; 15 for (i=p+1;i<=n;i++) 16 rsum[i]=a[i]>B?1:-1, 17 rsum[i]+=rsum[i-1], 18 rnum[rsum[i]+n]++; 19 for (i=-n;i<=n;i++) 20 ans+=lnum[i+n]*rnum[-i+n]; 21 printf("%d",ans); 22 return 0; 23 }