首页 > 编程语言 >排列中的数值问题(改编自NOIP2018程序填空第2大题)

排列中的数值问题(改编自NOIP2018程序填空第2大题)

时间:2023-09-11 20:35:45浏览次数:59  
标签:下标 ldots int 大题 链表 leftrightarrow 填空 节点 改编自

题目描述

对于一个 \(1\) 到 \(n\) 的排列 \(p_1, p_2, \ldots, p_n\)(即 \(1\) 到 \(n\) 中每一个数在数列 \(p\) 中出现了恰好一次),令 \(q_i\) 为第 \(i\) 个位置之后第一个比 \(p_i\) 值更大的位置,如果不存在这样的位置,则 \(q_i = n + 1\)。

举例来说,如果 \(n = 5\) 且 \(p\) 为 \(\{ 1, 5, 4, 2, 3 \}\),则 \(q\) 为 \(\{ 2, 6, 6, 5, 6 \}\)。

现在给你排列 \(p\),求出它对应的数列 \(q\)。

输入格式

第一行,一个整数 \(n(1 \le n \le 10^5)\)。

第二行,\(n\) 个整数 \(p_1, p_2, \ldots, p_n\)。数据保证 \(p\) 是一个 \(1\) 到 \(n\) 的排列。

输出格式

输出共一行,包含 \(n\) 个整数 \(q_1, q_2, \ldots, q_n\),两两之间以一个空格分隔。

样例输入

5
1 5 4 2 3

样例输出

2 6 6 5 6

题解

用双向链表来解决这个问题。

首先,排列 \(p_1, p_2, \ldots, p_n\) 中的每个数字都对应有一个点,\(p_i\)(下标为 \(i\) 的元素)对应双向链表里面编号为 \(i\) 的那个节点。

特殊地,节点 \(1\) 左边额外创建一个编号为 \(0\) 的点;节点 \(n\) 右边创建一个编号为 \(n + 1\) 的点。

如下:

\(\mathtt{(0)} \leftrightarrow (1) \leftrightarrow (2) \leftrightarrow (3) \leftrightarrow \ldots \leftrightarrow (n-1) \leftrightarrow (n) \leftrightarrow \mathtt{(n+1)}\)

其中:节点 \(0\) 和 \(n+1\) 是两个特殊的点,他们的作用主要是方便待会儿删除节点。

对于这个双向链表中编号为 \(1 \sim n\) 范围内的所有点来说,数值最小的那个点具有的性质是(假设当前双向链表中数值最小的那个节点是节点 \(x\)):

这个链表当中其它节点对应的数值都比它大。

从而可以推导出:

这个节点对应的元素右边离他最近的那个数值大于它的元素的下标就是这个节点的有指针指向的那个节点的编号。

问题来了?如何确定第 \(i\) 小的数的下标。
答:因为 \(p\) 是一个排列,所以我们可以再开一个数组 a[],用 \(a[x]\) 表示第 \(x\) 小的元素的下标。

接着,当我们输入 \(p_i\) 之后,可以得到 \(a[p_i] = i\)。

然后,在创建到双向链表后,就可以循环 \(i = 1 \to n\),求 \(a[i]\) 的有指针指向的下标(就是 \(q_{a[i]}\))

\(q_i\) 可以如何表示?

因为在删除节点 \(a[i]\) 的时候,\(r_{a[i]}\) 就是 \(q_{a[i]}\),而删除节点 \(a[i]\) 的时候,没有改变 \(r_{a[i]}\)(以后也不会改变),所以 \(r_{a[i]}\) 对应的就是 \(q_{a[i]}\)。

\(\Rightarrow\) \(r_i\) 就是 \(q_i\)。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, x, l[maxn], r[maxn], a[maxn];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x;
        a[x] = i;
    }
    for (int i = 0; i <= n; i++) {
        r[i] = i + 1;
        l[i + 1] = i;
    }
    for (int i = 1; i <= n; i++) {
        x = a[i];
        r[l[x]] = r[x];
        l[r[x]] = l[x];
    }
    for (int i = 1; i <= n; i++)
        cout << r[i] << " ";
    return 0;
}

标签:下标,ldots,int,大题,链表,leftrightarrow,填空,节点,改编自
From: https://www.cnblogs.com/quanjun/p/17694420.html

相关文章

  • 中文完形填空
    本文通过ChnSentiCorp数据集介绍了完型填空任务过程,主要使用预训练语言模型bert-base-chinese直接在测试集上进行测试,也简要介绍了模型训练流程,不过最后没有保存训练好的模型。一.完形填空完形填空应该大家都比较熟悉,就是把句子中的词挖掉,根据上下文推测挖掉的词是什么。二.准......
  • 【题解】P8679 [蓝桥杯 2019 省 B] 填空问题 题解
    P8679[蓝桥杯2019省B]填空问题题解题目传送门欢迎大家指出错误并联系这个蒟蒻更新日志2023-05-2521:02文章完成2023-05-2711:34文章通过审核2023-06-2021:03优化了文章代码格式试题A:组队【解析】本题是一道经典的DFS搜索题,每次对各号位的选手进行DFS,......
  • 【题解】P8741 [蓝桥杯 2021 省 B] 填空问题 题解
    P8741[蓝桥杯2021省B]填空问题题解题目传送门欢迎大家指出错误并联系这个蒟蒻更新日志2023-05-0923:19文章完成2023-05-0923:20通过审核2023-06-2021:03优化了文章代码格式试题A:空间【解析】本题考察计算机存储的基础知识,只要掌握空间存储的换算方法,就能......
  • 期末大题复习
    1.请描述TCP协议中标志位ACK、SYN、FIN、RST的含义,并叙述下TCP三次握手建立连接的过程 ACK(Acknowledge):表示确认号字段有效,通知接收方收到前一个数据包的序号,确认序号无误。一般每次收到数据都会回复一个包含ACK标志的确认包,这样对方才知道自己发送的数据已经被对方所接收。......
  • 复旦大学2022--2023学年第二学期(22级)高等代数II期末考试第八大题解答
    八、(10分) 设$n$阶实方阵$A$满足$A^3=A$,证明: 若对任意的实列向量$x$,均有$x'A'Ax\leqx'x$,则$A$是实对称阵.证法一(几何证法) 将题目转换成几何语言:设$\varphi$是$n$维欧氏空间$V$上的线性算子,满足$\varphi^3=\varphi$,若对$V$中任一向量$v......
  • 填空题
    1、将包含在网页内的动态信息创建为参数的函数是。web_reg_save_param 2、所谓的就是指有始有终、一系列的操作。会话 3、如图所示的网上视频点播系统,下载电影模块并发用户数为()。190 4、如图所示是某性能测试的数据库和web应用服务器资源分析图,可以看出,系统调优是应......
  • Handler面试必问八大题:如何深挖原理进大厂?1万+字带你详细剖析
    前言Handler一直是面试过程中的常客,我们今天来看看围绕Handler究竟能玩出那些花儿来。Handler机制几乎是Android面试时必问的问题,虽然看过很多次handler源码,但是有些面试官问的问题却不一定能够回答出来,趁着机会下面总结一下面试中所覆盖的Handler知识点。题目层次1.简述Handler的......
  • 完形填空记录
    061813/20holdme是用arms执行的,不是用hands执行的inspect/inspire看混了Ithasbeenalongtimesincehecalledmyname.意思是他已经很久没有叫我的名字了父亲阿尔兹海默症,ourconversationmyrepeatattimesorbefilledwithsilence所以和她说话是pr......
  • 填空题
    1、结构化分析方法的分析策略是:自顶向下、逐步求精2、衡量模块独立性的两个定性标准:耦合性和内聚性3、工厂模式分为:简单工厂、工厂方法、抽象工厂三种4、面向对象程序设计六大基本原则:单一职责、开闭原则、接口隔离、依赖倒转、里氏代换、迪米特5、设计模式遵循的原则:开闭原则......
  • 填空题课件
    场景布局 代码实现 ......