zoukankan      html  css  js  c++  java
  • codeforces 626E Simple Skewness

    2017-08-02 23:12:52

    writer:pprp

    题目大意:给你n个数,从n个数中选取几个数,使平均数和中位数的差值最大,将选取的个数还有选取的数字找出;

    算法分析:先枚举,再三分

    枚举中位数,可以证明中位数一定是一个,而不是两个组成的。

    三分主要用于类似于二次函数的曲线中,有极大或者极小值


    代码及分析如下:

    #include <iostream>
    #include <algorithm>
    #include <stdio.h>
    #include <cstdlib>
    
    using namespace std;
    typedef long long ll;
    const ll maxn = 200050;
    const ll INF = 0x3f3f3f3f;
    
    ll a[maxn];
    ll sum[maxn];//sum数组是记录了从1到i的总和
    
    int main()
    {
        ll n;
    
        cin >> n;
    
        for(ll i = 1; i <= n ; i++)
        {
            scanf("%lld",&a[i]);
        }
    
        sort(a+1,a+1+n);
        sum[0] = 0;
    
        //完成sum的赋值
        for(ll i = 1; i <= n; i++)
        {
            sum[i] = sum[i - 1] + a[i];
        }
    
        //对n = 1和 n = 2的情况进行特判
        if(n == 1 || n == 2)
        {
            printf("1
    ");
            printf("%lld
    ",a[1]);
            return 0;
        }
    
        ll l, r; //represent left and right
        ll m1, m2; //三分之一点处的长度,和三分之二处的长度
        ll s1, s2; //分别代表m1/m2时的总和(不包括枚举的点)
        ll mark_sum = 0, mark_len = 0, mark_mid = 1;//作为标记
        ll ssum = 0, len = 0, mid = 1 ;  //初始化
    
        //头和尾不可能所以从 2到n-1
        for(ll i = 2 ; i <= n - 1 ; i++)
        {
            l = 1;
            r = min(n-i,i-1);//看看左右两边哪个更短,r是长度不是角标
            for(ll j = 1; j <= 100; j++)//估计了一个数:100
            {
                m1 = (2 * l + r) / 3; //三分之一点到右端的距离
                m2 = (l + 2 * r + 2) / 3;//为了向上取整才加上2,三分之二点到右端的距离
    
                s1 = sum[i] - sum[i - m1 - 1] + sum[n] - sum[n - m1];
                s2 = sum[i] - sum[i - m2 - 1] + sum[n] - sum[n - m2];
                if(s1 * (2 * m2 + 1) < s2 * (2 * m1 + 1)) //2 * m + 1是总个数,这个比较的是平均值得大小
                {
                    l = m1 + 1;   //三分转移,从右往左看,从r处往左侧理解
                }
                else
                {
                    r = m2 - 1;   //三分转移
                }
            }
            ssum = sum[i] - sum[i - l - 1] + sum[n] - sum[n - l] - (2 * l + 1) * a[i];
            len = l;//记录长度为len
            mid = i;//记录下来枚举的点的坐标
            if(ssum*(2 * mark_len + 1) > mark_sum * (2 * len + 1))//取最大值
            {
                mark_sum = ssum;
                mark_len = len;
                mark_mid = mid;
            }
    
        }
    
        //输出个数
        cout << mark_len * 2 + 1 << endl;
    
        //为了格式
        ll flag = 1;
        for(ll i = mark_mid - mark_len ; i <= mark_mid ; i++)  //输出前一半
        {
            if(flag)
            {
                flag = 0;
                printf("%lld",a[i]);
            }
            else
            {
                printf(" %lld",a[i]);
            }
        }
    
        //输出后一半
        for(ll i = n - mark_len + 1; i <= n ; i++)
                printf(" %lld",a[i]);
                printf("
    ");
    
    
    
        return 0;
    }

     很奇怪,一开始用cin , cout来做就不行,采用printf还有scanf的时候可以,还有要用%lld

  • 相关阅读:
    deeplearning.ai 卷积神经网络 Week 1 卷积神经网络
    deeplearning.ai 构建机器学习项目 Week 2 机器学习策略 II
    deeplearning.ai 构建机器学习项目 Week 1 机器学习策略 I
    deeplearning.ai 改善深层神经网络 week3 超参数调试、Batch Normalization和程序框架
    deeplearning.ai 改善深层神经网络 week2 优化算法
    deeplearning.ai 改善深层神经网络 week1 深度学习的实用层面
    cs231n spring 2017 lecture8 Deep Learning Networks
    cs231n spring 2017 lecture7 Training Neural Networks II
    cs231n spring 2017 lecture6 Training Neural Networks I
    cs231n spring 2017 Python/Numpy基础
  • 原文地址:https://www.cnblogs.com/pprp/p/7277376.html
Copyright © 2011-2022 走看看