构造+有序集合,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;
}
相关推荐
挺菜的1 分钟前
【算法刷题记录(简单题)002】字符串字符匹配(java代码实现)
java·开发语言·算法
凌肖战3 小时前
力扣网编程55题:跳跃游戏之逆向思维
算法·leetcode
88号技师4 小时前
2025年6月一区-田忌赛马优化算法Tianji’s horse racing optimization-附Matlab免费代码
开发语言·算法·matlab·优化算法
ゞ 正在缓冲99%…5 小时前
leetcode918.环形子数组的最大和
数据结构·算法·leetcode·动态规划
Kaltistss6 小时前
98.验证二叉搜索树
算法·leetcode·职场和发展
知己如祭6 小时前
图论基础(DFS、BFS、拓扑排序)
算法
mit6.8246 小时前
[Cyclone] 哈希算法 | SIMD优化哈希计算 | 大数运算 (Int类)
算法·哈希算法
c++bug6 小时前
动态规划VS记忆化搜索(2)
算法·动态规划
哪 吒6 小时前
2025B卷 - 华为OD机试七日集训第5期 - 按算法分类,由易到难,循序渐进,玩转OD(Python/JS/C/C++)
python·算法·华为od·华为od机试·2025b卷
军训猫猫头6 小时前
1.如何对多个控件进行高效的绑定 C#例子 WPF例子
开发语言·算法·c#·.net