蓝桥集训之小朋友排队

本文介绍了一种使用归并排序的方法来计算一个小朋友在排队过程中需要进行的交换次数,通过统计每个位置上比该小朋友高的小朋友数量和比他低的,从而简化求解过程。
摘要由CSDN通过智能技术生成

蓝桥集训之小朋友排队

  • 核心思想:归并排序

    • 可证明每个小朋友交换的次数为 左边比他高的人数 + 右边比他低的人数
    • 所以求出上述值 再k*(k+1)/2 求和即可
    • 简化为用归并排序求人数
  •   #include<iostream>
      #include<algorithm>
      #include<cstring>
      
      #define x first
      #define y second
      using namespace std;
      const int N = 100010;
      typedef long long LL;
      typedef pair<int,int> PII;
      
      PII q[N],t[N];
      int n;
      int sum[N];
      LL res;
      
      void merge_sort(int l,int r)
      {
          if(l==r) return;
          int mid = l+r >>1;
          merge_sort(l,mid) , merge_sort(mid+1,r);
          int i = l,j = mid + 1,k=0;
          while(i<=mid && j <= r)
          {
              if(q[i] <= q[j])
              {
                  sum[q[i].y] += j - mid -1;  //当q[i]<=q[j]时 因为左右区间都已经排好序 则mid+1 - j 的所有数都比q[i]要小 加的是后面小的数
                  t[k++] = q[i++];
              }
              else
              {
                  sum[q[j].y] += mid - i + 1;  //i - mid的所有数都比q[j]要大 加的是前面大的数
                  t[k++] = q[j++];
              }
          }
          while(i<=mid) 
          {
              sum[q[i].y] += j - mid -1;  //说明q[i]剩的都是最大的 mid+1 - j的所有数都比它小
              t[k++] = q[i++];
          }
          while(j<=r) t[k++] = q[j++];  //说明q[j]剩最大的 不用加
          for(int i=l,j=0;i<=r;i++,j++) q[i] = t[j];
          return ;
      }
      
      int main()
      {
          cin>>n;
          for(int i=0;i<n;i++) cin>>q[i].x,q[i].y = i;  //x记录数值 y记录下标
      
          merge_sort(0,n-1);
          for (int i = 0; i < n; i ++ ) res += (LL)sum[i] * (sum[i] + 1) / 2;
          cout<<res;
      }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光男孩01

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值