zoukankan      html  css  js  c++  java
  • [CF1023D] Array Restoration

    Description

    给你一个长度为 (n) 的数列,初始全部为 (0) ,你可以任意(任选区间)进行 (q) 次操作,第 (i) 次操作使 ([l_i,r_i]) 内的数全部变为 (i) ,你必须进行全部 (q) 次操作,且每个操作区间都不能为空,所有操作区间的并必须为 ([1,n])。现在给你一个数列,其中 (0) 代表这个位置可以是任何数,问你能否通过上述的 (q) 次操作得到这个数列。输出方案。

    Solution

    以下 (m) 即为题面中的 (q)

    无解的判定

    如果两个数之间存在比它们小的数,则无解

    如果序列中不存在值为 (m) 的数,则无解

    解的构造

    考虑为 (0) 的位置需要怎样处理

    • 如果数列中没有 (m),则优先填 (m)

    • 如果某个位置的左侧右侧同时存在 (x),则该位置 (ge x),换言之我们在这个位置需要取它左边右边都有的数中的最大值

    • 否则填 (1)

    如何维护

    考虑维护一个 std::set,在某个数第一次出现时 insert(x),最后一次出现时 erase(x)

    那么我们每次取 *s.rbegin() 即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    
    int n,a[N],m,l[N],r[N];
    
    signed main() {
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>a[i];
    
        for(int i=1;i<=n;i++) r[a[i]]=i;
        for(int i=n;i>=1;--i) l[a[i]]=i;
    
        set<int> s;
        int fg=*max_element(a+1,a+n+1)==m;
        for(int i=1;i<=n;i++) {
            if(a[i]) {
                if(i==l[a[i]]) s.insert(a[i]);
                if(i==r[a[i]]) s.erase(a[i]);
                if(s.size()>0 && a[i]<*s.rbegin()) {
                    puts("NO");
                    return 0;
                }
            }
            else {
                if(fg==0) {
                    fg=1;
                    a[i]=m;
                }
                else if(s.size()>0) {
                    a[i]=*s.rbegin();
                }
                else {
                    a[i]=1;
                }
            }
        }
        if(fg) {
            puts("YES");
            for(int i=1;i<=n;i++) cout<<a[i]<<" ";
        }
        else {
            puts("NO");
        }
    }
    
  • 相关阅读:
    关于nginx稳定版1.20.1 4层负载 stream模块失效
    Docker 容器内分析 java程序占用 cpu 高问题排查分析
    分组排序查第一第二的差值
    【album】语音合成技术
    8.juery
    7.dom
    6.对象
    5.函数
    4.数组
    3.JS
  • 原文地址:https://www.cnblogs.com/mollnn/p/12784780.html
Copyright © 2011-2022 走看看