构造+有序集合,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;
}
相关推荐
im_AMBER1 天前
数据结构 06 线性结构
数据结构·学习·算法
earthzhang20211 天前
【1028】字符菱形
c语言·开发语言·数据结构·c++·算法·青少年编程
papership1 天前
【入门级-算法-3、基础算法:二分法】
数据结构·算法
通信小呆呆1 天前
收发分离多基地雷达椭圆联合定位:原理、算法与误差分析
算法·目标检测·信息与通信·信号处理
丁浩6661 天前
Python机器学习---2.算法:逻辑回归
python·算法·机器学习
伏小白白白1 天前
【论文精度-2】求解车辆路径问题的神经组合优化算法:综合展望(Yubin Xiao,2025)
人工智能·算法·机器学习
无敌最俊朗@1 天前
数组-力扣hot56-合并区间
数据结构·算法·leetcode
囚生CY1 天前
【速写】优化的深度与广度(Adam & Moun)
人工智能·python·算法
码农多耕地呗1 天前
力扣94.二叉树的中序遍历(递归and迭代法)(java)
数据结构·算法·leetcode
懒羊羊不懒@1 天前
Java基础语法—最小单位、及注释
java·c语言·开发语言·数据结构·学习·算法