题意:
有一列1到n的n个数排列(n<=40000),现在有一个数m(1<=m<=n),我们可以从排列中取出子排列是包括了m的,而当m在这个子排列的长度为奇数并且m是这个排列中中间大的数,就称该排列为BestCoder Sequence.问有多少个BestCoder Sequence。
题解:
对于m为头或者为末的排列可以用扫过去O(n)的时间完成,关键是如何统计一个子序列m的位置在中间的.
其实也很好处理,比如先处理m为末的所有排列,过程中记录下比m大得数个数与比m小的个数之差.再扫描以m为头的所有序列,利用前面的记录结果就可以统计出m位置处于子序列中间的满足要求的子序列个数了.时间复杂度O(n).
Program:
#include<iostream> #include<stdio.h> #include<math.h> #include<string.h> #include<queue> #include<algorithm> #define MAXN 40002 #define ll long long #define oo 40000 using namespace std; int a[MAXN],dp[MAXN<<1]; int main() { int n,m,i,id,ans,x; while (~scanf("%d%d",&n,&m)) { for (i=1;i<=n;i++) { scanf("%d",&a[i]); if (a[i]==m) id=i; } ans=1; x=0; memset(dp,0,sizeof(dp)); for (i=id-1;i>=1;i--) { if (a[i]>m) x++; else x--; if (!x) ans++; dp[x+oo]++; } x=0; for (i=id+1;i<=n;i++) { if (a[i]>m) x++; else x--; if (!x) ans++; ans+=dp[(-x)+oo]; } printf("%d\n",ans); } return 0; }