zoukankan      html  css  js  c++  java
  • 蓝桥杯历年试题 小朋友排队

    问题描述
      n 个小朋友站成一排。现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。

      每个小朋友都有一个不高兴的程度。开始的时候,所有小朋友的不高兴程度都是0。

      如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。当要求某个小朋友第k次交换时,他的不高兴程度增加k。

      请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。

      如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。
    输入格式
      输入的第一行包含一个整数n,表示小朋友的个数。
      第二行包含 n 个整数 H1 H2 … Hn,分别表示每个小朋友的身高。
    输出格式
      输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。
    样例输入
    3
    3 2 1
    样例输出
    9
    样例说明
      首先交换身高为3和2的小朋友,再交换身高为3和1的小朋友,再交换身高为2和1的小朋友,每个小朋友的不高兴程度都是3,总和为9。
    数据规模和约定
      对于10%的数据, 1<=n<=10;
      对于30%的数据, 1<=n<=1000;
      对于50%的数据, 1<=n<=10000;
      对于100%的数据,1<=n<=100000,0<=Hi<=1000000。
     
    思路:
    逆序数的变形,不仅要求逆序数的对数,还要把对数明确到每一个单位,在求的过程中要注意排除相等的情况(如果有更方便的排除法麻烦留个言,感觉自己写的判断有点麻烦),用树状数组求也需要判断。
    使用了归并排序求逆序数的方法,把模板改了一下。
    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cmath>
    #include <map>
    #include <algorithm>
    #define LL long long int
    #define N 100005
    using namespace std;
    int cmp(int a,int b)
    {
        if(a==b) return 0;
        return a<b?-1:1;
    }
    struct node
    {
        int num;
        int ang;
    
    };
    LL ans[N];
    void MergeArr(node num[], int left, int mid, int right)
    {
        node AL[N], AR[N];
        int lenl=mid-left+1,lenr=right-mid;
        for (int i = 0;i < lenl;i++)
            AL[i] = num[left + i];
        for (int i = 0;i < lenr;i++)
            AR[i] = num[mid + 1 + i];
        int j = 0, k = 0,pos=left;
        int tempNum=-1,tempCnt=0;
        while (j < lenl&&k < lenr)
        {
            int fix=cmp(AL[j].num, AR[k].num);
            if (fix<=0)
            {
                num[pos++] = AL[j++],num[pos-1].ang+=k;
                if(num[pos-1].num==tempNum)
                    num[pos-1].ang-=tempCnt;
            }
            //else if(fix==-1) num[pos++] = AL[j++];
            else
                num[pos++] = AR[k++],num[pos-1].ang+=mid-(left+j)+1;//关键步骤
            if(fix>0)
            {
                if(num[pos-1].num==tempNum)
                    tempCnt++;
                else
                    tempNum=num[pos-1].num,tempCnt=1;
            }
    
        }
        while (j < lenl)
        {
            num[pos++] = AL[j++];
            num[pos-1].ang+=k;
            if(num[pos-1].num==tempNum)
                num[pos-1].ang-=tempCnt;
        }
        while (k < lenr)
            num[pos++] = AR[k++];
    }
    void MergeSort(node num[], int left, int right)
    {
        if (left < right)
        {
            int mid = (right + left) / 2;
            MergeSort(num, left, mid);
            MergeSort(num, mid+1, right);
            MergeArr(num, left, mid, right);
        }
    }
    LL mat(LL num)
    {
        return num*(num+1)/2;
    }
    node num[N];
    int n;
    int main()
    {
        cin.sync_with_stdio(false);
        while(cin>>n)
        {
            LL fuck=0;
            for(int i=0;i<n;i++)
                cin>>num[i].num,num[i].ang=0;
            MergeSort(num,0,n-1);
            for(int i=0;i<n;i++)
                fuck+=mat(num[i].ang);
    
            cout<<fuck<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Springboot整合dubbo搭建基本的消费、提供和负载均衡
    SpringBoot与Dubbo整合的三种方式
    Dubbo整合SpringBoot
    Java 如何有效地避免OOM:善于利用软引用和弱引用
    finalize的作用
    垃圾回收
    不同JDK版本之间的intern()方法的区别-JDK6 VS JDK6+
    Java8内存模型—永久代(PermGen)和元空间(Metaspace)
    to meet you
    Atomic long 和long的区别
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/6387507.html
Copyright © 2011-2022 走看看