链接:https://ac.nowcoder.com/acm/problem/19913
来源:牛客网
来源:牛客网
题号:NC19913
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数。
输入描述:
第一行为两个正整数n和b ,第二行为1~n 的排列。
输出描述:
输出一个整数,即中位数为b的连续子序列个数。
本题是一个前缀和和差分的变题,可以让小于b的数设置为-1,大于b的数的值设置为1。然后通过查看相加后的结果是否是0来判断是否是中位数(也就相当于b这个数左右两边的数数量一致,那么b一定是一个中位数)。然后就是如何记录的问题?可以先想左遍历如果相加的值等于0那么让结果ans加一,同时搞一个数组记录左边各种和的数量。然后在遍历右边的时候一边相加的值是否是0,一边看与右边各种和是否有对应的,如果有也可以直接加上。
代码:
//1 2 3 4 5 6 7
//使用差分求和的方式
#include <iostream>
#include <cstdio>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
int main() {
IOS;
int n, b, num;
cin>>n>>b;
int pos;
int a[n+1];
for (int i=1;i<=n;i++) {
cin>>num;
if (num<b) {
a[i] = -1;
}
if (num>b) {
a[i] = 1;
}
if (num==b) {
pos = i;
a[i] = 0;
}
}
const int maxn = 1e5+7;
int nm[maxn] = {};
//ans从1起步,因为还有自身这一个因素,所以至少是1
int sum = 0, ans = 1;
for (int i=pos-1;i>0;i--) {
sum += a[i];
nm[n+sum]++;
if (sum==0) {
ans++;
}
}
sum = 0;
for (int i=pos+1;i<=n;i++) {
sum += a[i];
ans += nm[n-sum];
if (sum==0) {
ans++;
}
}
cout<<ans;
return 0;
}

京公网安备 11010502036488号