【每日一题】5月22日中位数图

[CQOI2009]中位数图

https://ac.nowcoder.com/acm/problem/19913

题意

给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。中位数是指把所有元素从小到大排列后,位于中间的数

输入描述

第一行为两个正整数n和b ,第二行为1~n 的排列。

输出描述

输出一个整数,即中位数为b的连续子序列个数。

解析

首先我并不知道为啥名字要带个图,首先我们来看,这个序列中所有的数都是连续的,只不过排列顺序不对,**并且每一个数只有一个**,这就让这个题的难度降低了很多。
我们看这个题,要求我们求出这个数字b所在的区间b正好是中位数的区间,这个中位数我们要考虑几个地方:
1.这个区间中的数字的个数要为奇数
2.在这个序列中大于b的数字的个数要等与小于b的数字的个数。
通过上面这两个条件我们就可以做出这个题,我们首先把不需要的元素去掉,首先我们并不需要知道比数字b大的数字是啥,比他小的又是啥,我们可以把比他大的数字用1代替,比它小的数字用-1代替,然后和他相等的数字用0表示,这样子如果这个区间存在b并且这个区间的和为0,这样在这个区间中b就是这个区间的中位数。这里我们用前缀和来做(用前缀和可以很快的知道这个区间的和),因为可能会出现负数,所以我们采用map,或者加上一定的基数,比如我们用sum[1000]代替sum[0]这样子如果出现了sum[-2]那么就等于sum[998]

代码

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAXN=1e5+5;
ll a[MAXN];
map<int,int>mp;
int main(void){
    ll n,b,ans,now;
    ans=0;
    cin>>n>>b;
    for(int i=1;i<=n;++i){
        cin>>a[i];
        if(a[i]>b) a[i]=-1;
        else if(a[i]==b){
            a[i]=0;
            now=i;
        }
        else a[i]=1;
    }
    ll sum=0;
    for(int i=now;i<=n;++i){
        sum+=a[i];
        mp[sum]++;
    }
    sum=0;
    for(int i=now;i;--i){
        sum+=a[i];
        ans+=mp[-sum];
    }
    cout<<ans<<endl;
    return 0;
}
每日一题 文章被收录于专栏

写每日一题呀

全部评论

相关推荐

10-14 23:01
已编辑
中国地质大学(武汉) Java
CUG芝士圈:虽然是网上的项目,但最好还是包装一下,然后现在大部分公司都在忙校招,十月底、十一月初会好找一些。最后,boss才沟通100家,别焦虑,我去年暑假找第一段实习的时候沟通了500➕才有面试,校友加油
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务