• [CQOI2009]中位数图(思维、前缀和)


    链接:https://ac.nowcoder.com/acm/problem/19913
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld

    题目描述

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

    输入描述:

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

    输出描述:

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

    示例1

    输入

    7 4
    5 7 2 4 3 1 6

    输出

    4

    由于是 1~n 的一个排列,所以不用担心数字重复的问题。因为是一个奇数长度的连续子区间,那么中位数这个数一定在这个区间里,且这个区间大于中位数的数等于小于中位数的数。

    由于是求中位数,所以除了 b 以外的数的具体大小并不重要,重要的是该数比 b 大还是比 b 小。我们用 a[i] = -1 代表该数比 b 小,用 a[i] =1 代表该数比 b 大。

    由连续区间,很容易让人联想到前缀和。在这题中,我们使用前缀和来表示从当前数到 b 的区间中,比 b 大的数和比 b 小的数的个数的差。由于这个差可能为负,所以我们可以用map存。

    这样的话,该问题转化为,求有多少个区间的和为0,并且包含数字b的位置。

    然后从b的位置pos往前计算和sum,然后看pos右遍有没有出现-sum,看前面是不是已经存过了,存过了就加起来前面存的个数即可。

    具体做法:

    在读入的时候,将大于中位数的数据赋值 1 ,小于中位数的数据赋值 1 ,等于中位数的数据赋值 0 ,并记录中位数的下标,左右遍历统计即可。

    左遍历的时候如果区间和为sum,并利用 map 查询右边区间和为 -sum 的情况,如果右边有区间和为-sum ,则可以与左边的sum 配对。

    注意:中位数b单独一个数字也是一个区间。

     1 #include <bits/stdc++.h>
     2 typedef long long LL;
     3 #define pb push_back
     4 #define mst(a) memset(a,0,sizeof(a))
     5 const int INF = 0x3f3f3f3f;
     6 const double eps = 1e-8;
     7 const int mod = 1e9+7;
     8 const int maxn = 1e5+10;
     9 using namespace std;
    10 
    11 int a[maxn];
    12 map<int,int> mp;
    13 
    14 int main()
    15 {
    16     #ifdef DEBUG
    17     freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout);
    18     #endif
    19     
    20     int n,m;
    21     scanf("%d %d",&n,&m);
    22     int pos;
    23     for(int i=1;i<=n;i++)
    24     {
    25         scanf("%d",&a[i]);
    26         if(a[i]>m) a[i]=1;
    27         else if(a[i]<m) a[i]=-1;
    28         else pos=i, a[i]=0;
    29     }
    30     mp[0]++;
    31     int sum = 0;
    32     for(int i=pos+1;i<=n;i++)
    33     {
    34         sum+=a[i];
    35         mp[sum]++;
    36     }
    37     int ans = 0;
    38     sum = 0;
    39     for(int i=pos;i>=1;i--)
    40     {
    41         sum += a[i];
    42         if(mp.count(-sum)) ans += mp[-sum];
    43     }
    44     printf("%d
    ",ans);
    45     
    46     return 0;
    47 }

    -

  • 相关阅读:
    P2622 关灯问题II(关灯问题)
    P1140 相似基因
    Choose and Divide UVa 10375
    Disgruntled Judge UVA
    Color Length UVA
    P1052 过河
    P1026 统计单词个数
    Balanced Number HDU
    The SetStack Computer UVA
    Urban Elevations UVA
  • 原文地址:https://www.cnblogs.com/jiamian/p/13234468.html
Copyright © 2020-2023  润新知