美文网首页
中位数图

中位数图

作者: Cralyon | 来源:发表于2019-12-09 15:43 被阅读0次

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K

    一、题目内容

    题目描述

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

    输入描述:

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

    输出描述:

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

    示例1

    输入

    7 4
    5 7 2 4 3 1 6

    输出

    4

    二、解题思路

    乍一看,有没有给数组一个快速排序的冲动?小的放左边,大的放右边,balabalabala。其实这里并没有快排这么多工序,我们知道初始化比较值b,在读入数组(a)过程中,同时初始化一个相同size的数组(flag),将当前下标的值与b的大小关系并存储在相应的位置,小于b的为-1,大于b的为1。接下来,以b为中点:

    1.我们需要先遍历左边的,使用s保留每次叠加的值(s = \sum^{n}_{i->n}{flag_i}),使用数组f记录当前值s为下标的个数【用于右侧遍历时使用】,若s = 0,则符合题意要求,所以ans+1;
    2.然后再遍历右边的,同样若s = 0,则ans+1,若当前值s取反为下标在数组f中有意义,则ans += f[-s + MAXN]【这是因为左边树我们已经在数组f保存过节点s(下标)具有的值,若右边树节点s(下标)在f处有值,则构成中位数图,那么新增f在s处的值的组合数】;
    3.最终我们再算上"b"自己,则++ans为最终结果。

    代码实操

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 10;
    int a[MAXN], f[MAXN * 2], flag[MAXN], pos;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        int n, b;
        cin >> n >> b;
        for(int i = 1; i <= n; i++) {
            cin >> a[i];
            if (a[i] == b) {
                pos = i;
            } else if (a[i] < b) {
                flag[i] = -1;
            } else {
                flag[i] = 1;
            }
        }
        int s = 0, ans = 0;
        ///左边
        for(int i = pos - 1; i >= 1; i--) {
            s += flag[i];
            f[s + MAXN]++;
            if (s == 0) ans++;
        }
        s = 0;
        ///右边
        for(int i = pos + 1; i <= n; i++) {
            s += flag[i];
            if (s == 0) ans++;
            ans += f[-s + MAXN];
        }
        cout << ++ans << endl;
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:中位数图

          本文链接:https://www.haomeiwen.com/subject/eibbgctx.html