E1.Median on Segments (Permutations Edition)
You are given a permutation p1,p2,…,pn. A permutation of length n is a sequence such that each integer between 1 and n occurs exactly once in the sequence.
Find the number of pairs of indices (l,r) (1≤l≤r≤n) such that the value of the median of pl,pl+1,…,pr is exactly the given number m.
The median of a sequence is the value of the element which is in the middle of the sequence after sorting it in non-decreasing order. If the length of the sequence is even, the left of two middle elements is used.
For example, if a=[4,2,7,5] then its median is 4 since after sorting the sequence, it will look like [2,4,5,7] and the left of two middle elements is equal to 4. The median of [7,1,2,9,6] equals 6 since after sorting, the value 6 will be in the middle of the sequence.
Write a program to find the number of pairs of indices (l,r) (1≤l≤r≤n) such that the value of the median of pl,pl+1,…,pr is exactly the given number m.
Input
The first line contains integers n and m (1≤n≤2⋅105, 1≤m≤n) — the length of the given sequence and the required value of the median.
The second line contains a permutation p1,p2,…,pn (1≤pi≤n). Each integer between 1 and n occurs in p exactly once.
Output
Print the required number.
Examples
Input
5 4
2 4 5 3 1
Output
4
Input
5 5
1 2 3 4 5
Output
1
Input
15 8
1 15 2 14 3 13 4 8 12 5 11 6 10 7 9
Output
48
Note
In the first example, the suitable pairs of indices are: (1,3), (2,2), (2,3) and (2,4).
题意:
给n和m,然后给一组1-n的排列
问有多少个连续子序列,中位数为m
思路:
因为是排列,所以m的位置是唯一的,首先肯定是找到m的位置pos
中位数为m,则连续序列肯定包含位置pos
逆序遍历(pos-1)-1,用cnt记录大于m和小于m的数的差值,并用mark[]标记cnt出现的次数
顺序遍历(pos+1)-n,用cnt同上记录
用第二次的cnt和第一次的mark数组来找连续序列的个数:
两个位置之间的(大于-小于)差值为0或者1则满足条件
讲的不是很清楚,如果想不明白具体操作的话直接看代码就行了
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
map<int,int>mark;
int a[maxm];
signed main(){
int n,m;
cin>>n>>m;
int pos=1;//m的位置
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]==m)pos=i;
}
int ans=0;//答案
int cnt=0;//大于mid的数减去小于mid的数
mark[0]++;//pos的位置cnt为0
for(int i=pos-1;i>=1;i--){//注意这里是从(pos-1)到1,是逆序的!
if(a[i]>m){
cnt++;
}else{
cnt--;
}
mark[cnt]++;
}
ans+=mark[0]+mark[1];//组成i-pos
cnt=0;
for(int i=pos+1;i<=n;i++){
if(a[i]>m){
cnt++;
}else{
cnt--;
}
ans+=mark[-cnt];//和小于pos的组成0
ans+=mark[-cnt+1];//和小于pos的组成1
}
cout<<ans<<endl;
return 0;
}