构造+有序集合,CF 1023D - Array Restoration

一、题目

1、题目描述

2、输入输出

2.1输入
2.2输出

3、原题链接

1023D - Array Restoration


二、解题报告

1、思路分析

先考虑合法性检查:

对于数字x,其最左位置和最右位置 之间如果存在数字比x小,则非法

由于q次操作,第q次操作是最后一次操作,所以数组中应该有q,即没q非法

这个合法性检查是很简单的,我们可以线段树,树状数组,分块,set......

考虑如何构造?

对于每个0,如果处于若干个数字的区间内,那么我们应该填的数字不能比这些区间中最大那个小

同时如果数组没有q,我们优先填q

算法流程:

预处理数组最大值ma,每个数字最左下标L[],最右下标R[]

遍历数组,用一个有序集合st来维护当前遇到的区间左端点

遇到0:

如果ma < q,那么我们填q,ma = q

否则,如果st非空,填st中最大那个

否则,填1

非0:

如果i == L[a[i]],a[i] 入st

如果 i == R[i], a[i] 出st

如果a[i] < min(st),非法输出NO

2、复杂度

时间复杂度: O(NlogN)空间复杂度:O(N)

3、代码详解

复制代码
 ​
cpp 复制代码
#include <bits/stdc++.h>
#define sc scanf
using i64 = long long;
using i128 = __int128;
using PII = std::pair<int, int>;
constexpr int inf32 = 1e9 + 7;
constexpr i64 inf64 = 1e18 + 7;
constexpr int P = 998244353;
constexpr double eps = 1e-6;

// #define DEBUG

void solve()
{
    int n, q;
    std::cin >> n >> q;
    std::vector<int> a(n), L(q + 1, -1), R(q + 1, -1);
    int ma = -1, mi = inf32;

    for (int i = 0; i < n; ++ i) {
        std::cin >> a[i], ma = std::max(ma, a[i]), mi = std::min(mi, a[i]);
        if (L[a[i]] == -1) L[a[i]] = i;
        R[a[i]] = i;
    }

    std::set<int> st;
    for (int i = 0; i < n; ++ i) {
        if (!a[i]) {
            if (ma < q)
                a[i] = q, ma = q;
            else if(st.size())
                a[i] = *std::prev(st.end());
            else
                a[i] = 1;
        }
        else {
            if (L[a[i]] == i && i < R[a[i]]) st.insert(a[i]);
            if (R[a[i]] == i && L[a[i]] < i) st.erase(a[i]);
            if (st.size() && a[i] < *std::prev(st.end())) {
                std::cout << "NO\n";
                return;
            }    
        }
    }
    if (ma < q) {
        std::cout << "NO\n";
        return;    
    }
    std::cout << "YES\n";
    for (int x : a)
        std::cout << x << ' ';

}

int main()
{
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    std::ios::sync_with_stdio(false), std::cin.tie(nullptr), std::cout.tie(nullptr);
    int _ = 1;
    // std::cin >> _;
    while (_--)
        solve();
    return 0;
}
相关推荐
吃好睡好便好10 小时前
用直接输入的方式创建矩阵
开发语言·人工智能·学习·线性代数·算法·matlab·矩阵
过期动态10 小时前
【RabbitMQ高级篇】生产者可靠性、MQ可靠性、消费者可靠性以及延迟队列的实现
java·数据结构·分布式·算法·rabbitmq·ruby
『昊纸』℃11 小时前
《C语言电子新-2026最新版》-编程语言与程序
数据结构·算法·程序设计·编程语言·软件开发
吃好睡好便好18 小时前
用while循环语句求和
开发语言·学习·算法·matlab·信息可视化
王璐WL19 小时前
【C语言入门级教学】函数的概念2
c语言·数据结构·算法
不知名的忻19 小时前
B 树与 B+ 树:面试完全指南
b树·算法·面试·b+树
运筹vivo@20 小时前
2657. 找到两个数组的前缀公共数组 | 难度:中等
算法·leetcode·职场和发展·哈希表
索木木20 小时前
NCCL SHARP 和 TREE算法
java·服务器·算法
心中有国也有家1 天前
hccl 架构拆解:昇腾集合通信库到底在做什么?
人工智能·经验分享·笔记·分布式·算法·架构
小O的算法实验室1 天前
2026年MCS,Q-learning增强MOPSO与改进DWA融合算法+复杂三维地形下特定移动机器人动态路径规划
算法