1 1 1 5 3 4 5 3 2 1
1 3HintFor the second case, {3},{5,3,2},{4,5,3,2,1} are Bestcoder Sequence.
出题人的解题思路:
将大于M的数标记为1,小于M的数标记为-1,M本身标记为0,则题目就是要求和为0并且包括M的连续序列的个数;用sum_i表示从第一个数到第i个数的标记的和,对于所有大于等于M的位置的i,我们要求小于M的位置的sum_j == sum_i的个数的和即为答案。该题简单来说其实就是给你一个序列,里面是1~N的排列,问你其中以M为中位数的奇数长度的区间有多少个
刚开始没有理解median number的意思,以为M要在区间的正中间,看了Clarification之后才发现是中位数的意思。
而M要是一个区间内的中位数,需要满足的是该区间内比M大的数的个数与比M小的数的个数相等
那么我们可以记录M左右两边区间比M大的和比M小的差值的个数,再相乘。
要想做到这一点,可以先遍历M的左边,记录差值个数,而遍历右边时直接加上与左边差值一样的即可。
比如说记录包含M的区间中M左侧有多少个比M大的数或比M小的数,比M大的和比M小的可以抵消,记录净差值
若仍不明白,可以提出,我会给以回复,并对解题报告作出修正,谢谢
放上一组测试数据,以供参考
Input
7 4
1 5 4 2 6 3 7
Output
8
Hint
{4}
{1,5,4}
{5,4,2}
{4,2,6}
{1,5,4,2,6}
{4,2,6,3,7}
{5,4,2,6,3}
{1,5,4,2,6,3,7}
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<math.h> #include<vector> #include<map> #include<set> #include<stdlib.h> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 #define ll __int64 using namespace std; const int N = 20005; const int inf = 1000000000; const int mod = 258280327; int a[2*N],s[2*N]; int main() { int n,m,i,k,j,ans; while(~scanf("%d%d",&n,&m)) { memset(s,0,sizeof(s)); for(i=0;i<n;i++) { scanf("%d",&a[i]); if(a[i]==m) k=i; } for(i=k,j=0;i>=0;i--) { if(a[i]!=m) a[i]>m?j++:j--; s[N-j]++; } for(i=k,ans=j=0;i<n;i++) { if(a[i]!=m) a[i]>m?j++:j--; ans+=s[N+j]; } printf("%d\n",ans); } return 0; }菜鸟成长记