曲师大2023大一新生排位赛-B.Sort题解

news2024/10/5 4:35:58

题目描述

插入排序是一种非常常见且简单的排序算法。王同学是一名大一的新生,今天许师哥刚刚在上课的时候讲了插入排序算法。

假设比较两个元素的时间为 O\left ( 1 \right ),则插入排序可以以 O\left ( n^2 \right ) 的时间复杂度完成长度为 n� 的数组的排序。不妨假设这 n 个数字分别存储在a_1,a_2,......,a_n​ 之中,则如下伪代码给出了插入排序算法的一种最简单的实现方式:
下面是插入排序的示范代码:


for (int i = 1; i <= n; i++)
      for (int j = i; j >= 2; j--)
            if (a[j] < a[j-1]) {
		  int t = a[j-1];
		  a[j-1] = a[j];
		  a[j] = t;
	    }


为了帮助王同学更好的理解插入排序,许师哥给他留下了这么一道课后作业:

许师哥给了一个长度为 n 的数组 a,数组下标从 1 开始,并且数组中的所有元素均为非负整数。王同学需要支持在数组 a 上的 Q 次操作,操作共两种,参数分别如下:
1 x v:这是第一种操作,会将 a 的第 x 个元素,也就是 a_x​ 的值,修改为 v。保证 1 \leq x \leq n, 1 \leq v \leq 10 ^9注意这种操作会改变数组的元素,修改得到的数组会被保留,也会影响后续的操作
 

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

许师哥不喜欢过多的修改,所以他保证类型 11 的操作次数不超过 50005000。

输入描述

第一行,包含两个正整数 n,Q\left ( 1 \leq n \leq 8000,1 \leq Q \leq 2 \times 10^5 \right ),表示数组长度和操作次数。
第二行,包含 n 个空格分隔的非负整数,其中第 i 个非负整数表示 a_i \left ( 1 \leq a _i \leq 10^9 \right )
接下来 Q 行,每行 2∼3个正整数,表示一次操作,操作格式见【题目描述】
输入数据保证 1 \leq x \leq n, 1 \leq v \leq 10 ^9,同时,在所有 Q 次操作中,至多有 5000 次操作属于类型一。

输出描述

对于每一次类型为 2 的询问,输出一行一个正整数表示答案。

样例

输入:

3 4
3 2 1
2 3
1 3 2
2 2
2 3

输出:

1
1
2

输入:

10 10
877332633 234569527 229171089 600324455 1458624 887548760 574229391 234569527 202374341 849045846
2 7
1 2 234569527
1 4 600324455
2 6
2 9
2 6
2 3
1 5 246345024
1 6 856960762
2 7

输出:

6
10
2
10
3
6

思路:

题目告诉我们至多5000次修改,很明显修改次数少,查询次数多。所以我们不能在查询时间进行排序操作的修改,但是可以在修改时间进行操作。
我们可以先对数据进行排序,原结构体数组记录排好序的下表,将排序结构体中对应好原数组的位置。
修改时间操作的理论:我将原来的数和修改后的数之间的下表进行修改,大于和小于这两个数的下表不需要修改,因为重新排序也不影响这两个数之外的位置,所以只需要修改原数和修改数区间内的下表即可。这样就可以可使用O(n)的时间复杂度完成这一操作
查询时间的理论:在修改时间同时维护这这两个结构体数组之间的对应关系,所以查询的时间复杂度是O(1)

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 8100;
struct node1
{
    int value,pxb;
}a[N];//原数组,对应的是该位置的值,该位置排序后的下标
struct node2
{
    int vlaue,yxb;
}b[N];//排序数组,对应的是该位置的值,该位置在原数组中对应的下标
bool cmp(node2 x,node2 y){
    if(x.vlaue == y.vlaue)
        return x.yxb < y.yxb;
    return x.vlaue < y.vlaue;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(NULL);cout.tie(NULL);
    int n,q;
    cin >> n >> q;
    for(int i = 1;i <= n;i++){
        int x;
        cin >> x;
        b[i].vlaue = x;
        b[i].yxb = i;
    }
    sort(b+1,b+1+n,cmp);
    // for(int i = 1;i <= n;i++){
    //     cout << b[i].vlaue << endl;
    // }
    for(int i = 1;i <= n;i++){
        a[b[i].yxb].value = b[i].vlaue;
        a[b[i].yxb].pxb = i;
    }
    // for(int i = 1;i <= n;i++){
    //     cout << a[i].pxb << " " << a[i].value << endl;
    // }
    while(q--){
        int op;
        cin >> op;
        if(op == 1){
            int x,v;
            cin >> x >> v;
            int yu = a[x].value;
            int xi = v;
            a[x].value = v;
            b[a[x].pxb].vlaue = v;
            int i = a[x].pxb;
            //两个循环只会进入一个
            //这个循环时说修改后的值比原来的值小了,用排序的数组往前找他自己的位置
            while(i != 1 &&( b[i].vlaue < b[i - 1].vlaue || (b[i].vlaue == b[i - 1].vlaue && b[i].yxb < b[i-1].yxb))){
                swap(b[i],b[i - 1]);
                a[b[i].yxb].pxb=i;
                a[b[i].yxb].value=b[i].vlaue;
                a[b[i - 1].yxb].pxb=i - 1;
                a[b[i - 1].yxb].value=b[i - 1].vlaue;
                i--;
            }
            //这个循环,修改后的值比原来的值大了,用排序数组往后找他自己的位置
            while(i != n &&( b[i].vlaue > b[i + 1].vlaue || (b[i].vlaue == b[i + 1].vlaue && b[i].yxb > b[i+1].yxb))){
                swap(b[i],b[i + 1]);//交换之后需要维护原来的对应关系
                a[b[i].yxb].pxb=i;
                a[b[i].yxb].value=b[i].vlaue;
                a[b[i + 1].yxb].pxb=i + 1;
                a[b[i + 1].yxb].value=b[i + 1].vlaue;
                i++;
            }
        }
        if(op == 2){
            int x;
            cin >> x;
            cout << a[x].pxb << "\n";
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/769246.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何将大批量将行驶证合并转为excel?

我们知道&#xff0c;金鸣识别小程序和网页在线版都支持将行驶证转为excel&#xff0c;但这二种方案只适合小量、零星的转换&#xff08;小程序只能一次提交4张图片&#xff0c;网页在线版只能一次提交5张&#xff09;&#xff0c;要想大批量识别&#xff0c;就要下载安装金鸣识…

栈与队列 理论基础

我们都知道栈和队列是STL&#xff08;C标准库&#xff09;里面的两个数据结构。 栈是前进后出&#xff0c;队列是先进先出 C标准库是有多个版本的&#xff0c;要知道我们使用的STL是哪个版本&#xff0c;才能知道对应的栈和队列的实现原理。 那么来介绍一下&#xff0c;三个最…

springboot项目自定义注解+Aop实现收集日志

一 工程结构 二 配置 2.1 配置pom <!--spring boot的启动类 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.…

Sentinel的线程隔离和熔断降级

上一节整理了Sentinel的限流&#xff0c;限流可以降低微服务的负载&#xff0c;避免因为高并发而故障&#xff0c;进而传递给其他相关服务而引发服务雪崩。以上仅为避免服务故障&#xff0c;而当某个服务真正故障时&#xff0c;如何处理才能防止服务雪崩&#xff1f; ⇒ Sentin…

二十一、vm 适配

目录&#xff1a; 1. 基础准备 2. 详解 一、基础准备 目的&#xff1a;前面我们通过0.1333vm x 对应的设计图像素&#xff0c;找到vm值&#xff0c;这个方法不准确&#xff0c;且操作复杂&#xff0c;有没有什么优化方法呢&#xff1f; 解决&#xff1a;vw的适配&#xff08;在…

Bard:一个可以描述图像的人工智能

Bard 是一个大型语言模型&#xff0c;可以对各种提示和问题进行交流和生成类似人类的文本。它接受了大量的文字和代码训练&#xff0c;可以生成文本、翻译语言、编写不同类型的创意内容&#xff0c;并以信息丰富的方式回答你的问题。 Bard 还可以识别图像。它可以识别图像中的…

python编程语言之进阶语法

迭代器 可迭代对象 讲迭代器之前&#xff0c;我们先了解一个概念&#xff1a;可迭代对象(Iterable)。 那么什么是可迭代&#xff1f;什么是对象&#xff1f; 迭代(Iteration)&#xff0c;是指通过遍历获取某容器内所有元素&#xff0c;特指遍历获取这个动作。 可迭代 (iter…

EasyCVR录像阈值配置未生效,是什么原因?

有用户反馈&#xff0c;在平台中设置了录像阈值不生效&#xff0c;导致磁盘爆满。针对该反馈&#xff0c;我们立即进行了排查。 EasyCVR基于云边端一体化架构&#xff0c;可支持多协议、多类型设备接入&#xff0c;在视频能力上&#xff0c;平台可实现视频直播、录像、回放、检…

用C语言对学生成绩进行排序(归并排序与基数排序)

一.前言 我们内部排序已经学了插入排序&#xff08;直接插入排序、折半插入排序、希尔排序&#xff09;&#xff0c;交换排序&#xff08;冒泡排序、快速排序&#xff09;&#xff0c;选择排序&#xff08;简单选择排序、堆排序&#xff09;&#xff0c;这些都属于内部排序&…

ShardingSphere分库分表实战之绑定表

&#x1f680; ShardingSphere &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&…

DAY48:动态规划(十二)完全平方数(类似零钱兑换)+单词拆分(注意背包思路!)

文章目录 279.完全平方数&#xff08;类似零钱兑换&#xff09;思路DP数组含义递推公式初始化遍历顺序 最开始的写法&#xff1a;有1个用例没过修改完整版总结 139.单词拆分&#xff08;递推公式注意&#xff09;思路1&#xff1a;遍历单词分割点DP数组含义递推公式初始化遍历顺…

基于Java+SpringBoot+Vue前后端分离旅游网站详细设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

导航菜单 改变背景色

直接参考官网上的案例即可 //active-text-color 点击时修改字体颜色 // background-color 背景色 // text-color 字体颜色<el-menudefault-active"2"class"el-menu-vertical-demo"open"handleOpen"close"handleClose"background…

Java:控制流程 + 数组 详解(原理 + 用法 + 例子)

目录 控制流程块作用域if 条件语句for while 循环switch 多重选择break continue 中断控制流程语句 大数值数组多维数组字符串类型数组Array.sort() 数组排序for each 循环 控制流程 块作用域 块&#xff08;即复合语句&#xff09;是指由一对大括号{}括起来的若干条简单的 Ja…

ARP解析MAC地址的全过程(ARP的工作机制)

目录 ARP解析MAC地址的过程&#xff1a; 源码等资料获取方法 以太网环境下&#xff0c;同一个网段的主机之间需要互相知道对方的MAC地址&#xff0c;才能访问。 TCP/IP协议栈从上层到下层的封装过程中&#xff0c;第三层封装需要知道目的IP&#xff0c;第二层封装需要知道目…

Linux下安装Mysql (CentOS 7) 详解

文章目录 前言环境检查查看是否安装MySql查看系统版本 源安装安装mysql的yum源官网下载从windows上传到linuxrz命令 方法2&#xff1a; 安装Mysql常见错误密钥问题安装后查看mysql是否可以工作查看是否安装成功启动服务 登录mysql配置文件方法&#xff08;免密码&#xff09; 使…

linux 安装 cuda

需求&#xff1a; inux 下安装 cuda 进程&#xff1a; 先查看一下系统版本 uname -a查看能支持什么版本的cudacuda toolkit 下载 wget https://developer.download.nvidia.com/compute/cuda/11.1.0/local_installers/cuda_11.1.0_455.23.05_linux.run sudo sh cuda_11.1.0_4…

MySql冷门但是很有用的语句

目录 1 查看当前的所有执行的进程 查看简略信息 查看详细信息 2 在所有数据库中查询包含某个字段的表 精确 模糊 1 查看当前的所有执行的进程 查看简略信息 show processlist 查看详细信息 show full processlist 终止进程 kill id 2 在所有数据库中查询包含某个字段…

gurobi安装vs配置gurobi

gurobi安装&vs配置gurobi 1、注册账号并登录 2、下载gurobi optimizer 3、获取license:User Portal (gurobi.com) online course可以免ip验证。 4、GENERATE NOW会生成&#xff0c;打开cmd进入gurobi安装路径&#xff08;如F:\gurobi1001\win64\bin>&#xff09;&am…

分布式事务 Seata

分布式事务 Seata 事务介绍分布式理论Seata 介绍Seata 部署与集成Seata TC Server 部署微服务集成 Seata XA 模式AT 模式AT 模式执行过程读写隔离写隔离读隔离 实现 AT 模式 TCC 模式TCC 模式介绍实现 TCC 模式 Saga 模式Seata 四种模式对比 事务介绍 事务&#xff08;Transac…