给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把全部元素从小到大排列后,位于中间的数。c++
输入格式:数组
第一行为两个正整数n和b,第二行为1~n的排列。spa
【数据规模】code
对于30%的数据中,知足n≤100;get
对于60%的数据中,知足n≤1000;it
对于100%的数据中,知足n≤100000,1≤b≤n。io
输出格式:class
输出一个整数,即中位数为b的连续子序列个数。map
输入样例#1:方法
7 4
5 7 2 4 3 1 6
输出样例#1:
4
首先题目有一个隐含的性质,由于是排列,而又保证\(b\)出现过,因此\(b\)在这\(n\)个数中有且只有一个
这道题能够\(O(n^2)\)经过统计前缀和拿到60分,咱们只关心相对大小,因此能够把大于\(b\)的设成1,小于\(b\)的设成-1
由于是中位数,因此先后的数字个数一定相等,在咱们设了1/-1以后,又多了一个条件,即左边的数字的和+右边数字的和=0(想想就知道了)
那么咱们就能够先统计一边的前缀和的个数,再在另外一边一边计算前缀和一边统计答案,由于可能会有负数,因此有两种方法,一种是把数组平移,一种是开\(map\)
具体结合代码(画一下)就懂了
#include<bits/stdc++.h> #define in(i) (i=read()) #define il extern inline #define rg register #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define lol long long using namespace std; const lol N=1e5+10; lol read() { lol ans=0, f=1; char i=getchar(); while (i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();} while (i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48), i=getchar(); return ans*f; } int n,m,sum,ans,pos,a[N]; map<int,int>cnt; int main() { in(n), in(m); for (rg int i=1;i<=n;i++) { in(a[i]); if(a[i]>m) a[i]=1; else if(a[i]==m) a[i]=0, pos=i; else a[i]=-1; } for (int i=pos;i<=n;i++) sum+=a[i], cnt[sum]++; sum=0; for (int i=pos;i>=1;i--) sum+=a[i], ans+=cnt[-sum]; cout<<ans<<endl; }