题面
题意:
Description
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
Input
第一行为两个正整数n和b ,第二行为1~n 的排列。
Output
输出一个整数,即中位数为b的连续子序列个数。
Sample Input
7 4
5 7 2 4 3 1 6
Sample Output
4
HINT
第三个样例解释:{4}, {7,2,4}, {5,7,2,4,3}和{5,7,2,4,3,1,6}
N<=100000
IDEA:
一道不错的思维题。我们把题意转化一下其实就是求区间
[
l
,
r
]
[l,r]
[l,r]的个数。我们令
m
a
x
x
[
i
]
maxx[i]
maxx[i]代表到第
i
i
i位大于
k
k
k的,
m
i
n
n
[
i
]
minn[i]
minn[i]代表到第
i
i
i位小于
k
k
k的个数。那么
1
1
1、
l
<
=
k
<
=
r
l<=k<=r
l<=k<=r
2
2
2、
m
a
x
x
[
r
]
−
m
a
x
x
[
l
−
1
]
=
=
m
i
n
n
[
r
]
−
m
i
n
n
[
l
−
1
]
maxx[r]-maxx[l-1]==minn[r]-minn[l-1]
maxx[r]−maxx[l−1]==minn[r]−minn[l−1],即区间
[
l
,
r
]
[l,r]
[l,r]内大于
k
k
k的数等于
[
l
,
r
]
[l,r]
[l,r]内小于
k
k
k的数。把式子转换一下就有
m
a
x
x
[
r
]
−
m
i
n
n
[
r
]
=
=
m
a
x
x
[
l
−
1
]
−
m
i
n
n
[
l
−
1
]
maxx[r]-minn[r]==maxx[l-1]-minn[l-1]
maxx[r]−minn[r]==maxx[l−1]−minn[l−1]
这样我们只需要分别枚举
r
r
r和
l
l
l然后记录下来差值,最后相乘在相加即可。如果
m
a
x
x
[
i
]
−
m
i
n
n
[
i
]
<
0
maxx[i]-minn[i]<0
maxx[i]−minn[i]<0的话,我们让它加上一个大点的数即可。
code:
/**************************************************************
Problem: 1303
User: codancer
Language: C++
Result: Accepted
Time:204 ms
Memory:18088 kb
****************************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+100;
int a[N];int maxx[N],minn[N];
ll L[1000000],R[1000000];
int main(){
int n,k;
cin>>n>>k;
int id;ll ans=0;
for(int i=1;i<=n;i++){
cin>>a[i];if(a[i]==k) id=i;
}
for(int i=1;i<=n;i++){
if(a[i]>k){
maxx[i]=maxx[i-1]+1;
minn[i]=minn[i-1];
}
else if(a[i]<k){
minn[i]=minn[i-1]+1;
maxx[i]=maxx[i-1];
}
else{
minn[i]=minn[i-1];
maxx[i]=maxx[i-1];
}
}
for(int r=id;r<=n;r++){
R[maxx[r]-minn[r]+400000]++;
}
for(int l=1;l<=id;l++){
L[maxx[l-1]-minn[l-1]+400000]++;
}
for(int i=0;i<1000000;i++){
if(L[i]&&R[i]) ans+=L[i]*R[i];
}
cout<<ans<<endl;
return 0;
}