插入排序

题目描述

H 老师给了一个长度为 \(n\) 的数组 \(a\),数组下标从 \(1\) 开始,并且数组中的所有元素均为非负整数。小 Z 需要支持在数组 \(a\) 上的 \(Q\) 次操作,操作共两种,参数分别如下:

\(1~x~v\):这是第一种操作,会将 \(a\) 的第 \(x\) 个元素,也就是 \(a_x\) 的值,修改为 \(v\)。保证 \(1 \le x \le n\)\(1 \le v \le 10^9\)注意这种操作会改变数组的元素,修改得到的数组会被保留,也会影响后续的操作

\(2~x\):这是第二种操作,假设 H 老师按照上面的伪代码\(a\) 数组进行排序,你需要告诉 H 老师原来 \(a\) 的第 \(x\) 个元素,也就是 \(a_x\),在排序后的新数组所处的位置。保证 \(1 \le x \le n\)注意这种操作不会改变数组的元素,排序后的数组不会被保留,也不会影响后续的操作

题目思路

根据题目描述,我们需要完成对数组a的插入排序操作,并能够回答查询操作。考虑到数组长度和操作次数可能较大,我们可以使用优化后的插入排序算法来解决这个问题。

优化后的插入排序算法的基本思想是:将待排序的元素与已排序的元素逐个比较并移动,找到合适的位置插入。不再使用交换操作,而是使用移动操作,这样可以减少元素的比较和交换次数。

我们可以按照以下步骤来实现此算法:

  1. 遍历数组a,从第二个元素开始(下标为1),依次将当前元素与其前面的有序序列中的元素进行比较。
  2. 当找到合适的插入位置时,将当前元素插入到该位置。
  3. 继续下一个元素的插入操作,直到遍历完整个数组。

而对于查询操作,我们可以使用另一个数组b来记录排序后的元素的位置,数组b的下标表示原数组a的下标,数组b的值表示在排序后的数组中的位置。

具体的解题思路如下:

  1. 读取输入的数组长度n和操作次数Q。
  2. 读取数组a的元素。
  3. 初始化数组b,将数组a的元素依次插入数组b的适当位置。
  4. 处理操作:
    • 如果操作类型是1,则修改数组a中对应位置的元素,并更新数组b对应位置的值。
    • 如果操作类型是2,则输出数组b中对应位置的值。
  5. 重复步骤4,直到处理完所有操作。

代码实现

#include <bits/stdc++.h>
using namespace std;
int q,n,a[8005];
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
      scanf("%d",&a[i]);
    for(int i=1;i<=q;i++)
    {
        int k,x,v;
        scanf("%d",&k);
        if(k==1)
        {
            scanf("%d%d",&x,&v);
            a[x]=v;
        }
        else
        {
            scanf("%d",&x);
            int m=0;
            for(int i=x-1;i>0;i--)
              if(a[i]>a[x])
                m++;
            for(int i=x+1;i<=n;i++)
              if(a[i]>=a[x])
                m++;
            printf("%d\n",n-m);
        }
    }
    return 0;
}
posted @ 2023-08-04 21:17  卡布叻-空白  阅读(29)  评论(0)    收藏  举报