zoukankan      html  css  js  c++  java
  • HDU 5701 中位数计数

      这题真的很恶心,做了一天,最后问学长,才懂题意是什么,原来我一直都没读懂题。这我真的就无语了,你的题意多两句话会死啊?你测试样例多两个例子就不行啊?真蛋疼,题意都不懂,还做个shi?

      题里说的是区间,所以必须是连续的,题里又说排好序后的中位数,所以也就相当于当输入1 4 2的时候,应该输出1 1 2, 前两个1能懂,但最后为什么是2呢?因为1个区间是他自己,还有1个区间是1 4 2,这里2是中位数,因为1 4 2排序之后是1 2 4,是中位数,所以1 4 2中的2就是中位数。

      理解了这个,看下面的题解就不费劲了。

    解题思路: 
    其实题目中说的很明白了,我们要求的中位数就是一个排好序的数列中中间的那个数,这个题要我们求的就是第 i 个数在多少包含其的区间中是中位数(求得是区间个数)。那么我们可以这么想,我们将这个数分成两个部分假设这个数的下标是i(初始时从1开始的)那么这两部分就是[1,i-1]和[i+1, n],我们可以每次暴力求这个两个区间内比它大的数和比它小的数。 
    现在在第一个区间内:如果一个数比当前这个数小那么sum++,否则sum–(因为不存在两个相同的数) 
    现在在第二个区间内:如果一个数比当前这个数大那么sum++,否则sum–(因为不存在两个相同的数) 
    那么在加和减的过程中如果遇到sum==0的情况那么它必定是一个区间的中位数用ans++,然后再定义两个数组num1[],num2[],因为在比较的过程中sum可能出现负数,那么我们只需要将这个数加上n就行了,即num1[n+sum]++,num2[sum+n]++;然后我们就是让相等的数进行相乘,(num1和num2初始化为0)最后输出就行了,在这里注意格式错误,最后一个没有空格,复杂度 O(2*n^2)。 
      我在解释下为什么要num1乘num2,因为num1中存的是前半部分sum的值出现的次数,比如num1[n+1]=2 就代表sum为1时出现2次,num2中存的是后半部分sum的值出现的次数,比如num2[n+1]=3 就代表sum为1时出现3次。这时他们就要相乘了,因为每一次num1都可以匹配所有的num2,比如刚才说的,那就是1次num1匹配3次num2,因为是2次,所以就是当了3+3=2*3=6次中位数。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    using namespace std;
    const int MAXN = 8000+5;
    typedef long long LL;
    int a[MAXN];
    int num1[MAXN*2],num2[MAXN*2];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            for(int i=1; i<=n; i++)
                scanf("%d",&a[i]);
            for(int i=1; i<=n; i++)
            {
                memset(num1, 0, sizeof(num1));
                memset(num2, 0, sizeof(num2));
                int sum = 0, ans = 1;;
                for(int j=i+1; j<=n; j++)
                {
                    if(a[i] > a[j])
                        sum--;
                    else
                        sum++;
                    if(sum == 0)
                        ans++;
                    num1[n+sum]++;
                }
                sum = 0;
                for(int j=i-1; j>0; j--)
                {
                    if(a[i] < a[j])
                        sum--;
                    else
                        sum++;
                    if(sum == 0)
                        ans++;
                    num2[n+sum]++;
                }
                for(int j=0; j<2*n; j++)
                    ans += num1[j]*num2[j];
                cout<<ans;
                if(i != n)
                    cout<<" ";
                else
                    puts("");
            }
        }
        return 0;
    }
  • 相关阅读:
    5 Things Every Manager Should Know about Microsoft SharePoint 关于微软SharePoint每个经理应该知道的五件事
    Microsoft SharePoint 2010, is it a true Document Management System? 微软SharePoint 2010,它是真正的文档管理系统吗?
    You think you use SharePoint but you really don't 你认为你使用了SharePoint,但是实际上不是
    Introducing Document Management in SharePoint 2010 介绍SharePoint 2010中的文档管理
    Creating Your Own Document Management System With SharePoint 使用SharePoint创建你自己的文档管理系统
    MVP模式介绍
    权重初始化的选择
    机器学习中线性模型和非线性的区别
    神经网络激励函数的作用是什么
    深度学习中,交叉熵损失函数为什么优于均方差损失函数
  • 原文地址:https://www.cnblogs.com/s1124yy/p/5677021.html
Copyright © 2011-2022 走看看