codeforces 1023 D Array Restoration (树状数组)

题面

在这里插入图片描述

题意

有一个长度为n的序列,你可以进行 q 次修改,第i次修改将区间 [l,r] 的数修改成 i ,涉及的 q次修改必须要覆盖区间中的每个数,q 次修改之后,将这个序列中的某些数变为0,得到一个新的序列(就是输入的序列),问你能不能通过这个新的序列求出一个变0之前的合法序列

题解

  1. 要求的这个字符串肯定是要有q的,因为q是最后一次修改,修改之后肯定有q,那么就要求输入的这个序列要么包含q,要么包含0(我们就可以将0变为q),如果输入的序列既没有q也没0,那么一定输出NO
  1. 要想有合法序列,那么就要保证输入的序列也合法,对于输入的序列,因为每次修改都是修改一段区间,而且修改之后肯定是变大的,所以两个相同数字区间是不可能出现比它小的数字的,,例如 6 5 6 肯定是不合法的,对于第6次修改,我们只能将一段区间的数修改为6且只有这一次机会,所以要修改只能是把5也一起修改,就不可能出现上述情况
  1. 知道这个性质,我们就可以用树状数组巧妙的判断是否为合法序列,对于第一次出现的数,我们可以标记一下比它小的数有多少,当第二次遇到这个数时,我们只要判断比它小的数是否多了,如果是多了,那么在这区间一定是有小于这个数的数了,设计的操纵不就是在一个位置添加1,然后查询前缀和(小于这个数的个数),妥妥的树状数组
  1. 对于输出,肯定是要连续的一段数字相同比较方便,所以对于0,我们直接让它等于前一个数即可,但是要注意,就是当输入的序列没有q时,我们要先将0转化为q(因为序列中必须出现一个q)

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 2e5 + 10;

int n, q;
int a[N], vis[N];
int tr[N];

int lowbit(int x) {
    
    
    return x & -x;
}

void add(int x, int c) {
    
    
    for (int i = x; i <= q; i += lowbit(i)) tr[i] += c;
}

int sum(int x) {
    
    
    int res = 0;
    for (int i = x; i; i -= lowbit(i)) res += tr[i];
    return res;
}

int main() {
    
    

    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    cin >> n >> q;
    for (int i = 1; i <= n; i++) cin >> a[i];

    bool flag = true;
    for (int i = 1; i <= n; i++) {
    
    
        if (a[i] == 0) continue;
        if (vis[a[i]]) {
    
       //说明之前出现过
            if (vis[a[i]] != sum(a[i])) {
    
      //说明中间出现过小于a[i]的数
                flag = false;
                break;
            }
        }
        add(a[i], 1);
        vis[a[i]] = sum(a[i]);
    }

    if (flag) {
    
    
        bool zero = false, isq = false;
        for (int i = 1; i <= n; i++) {
    
    
            if (a[i] == 0) zero = true;
            if (a[i] == q) isq = true;
        }
        if (!(zero || isq)) {
    
    
            cout << "NO" << endl;
        } else {
    
    
            a[0] = 1;
            for (int i = 1; i <= n; i++) {
    
    
                if (a[i] == 0) {
    
    
                    if (!isq) {
    
    
                        a[i] = q;
                        isq = true;
                    } else {
    
    
                        a[i] = a[i - 1];
                    }
                }
            }
            cout << "YES" << endl;
            for (int i = 1; i <= n; i++) {
    
    
                cout << a[i] << " ";
            }
            cout << endl;
        }
    } else {
    
    
        cout << "NO" << endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44791484/article/details/114107011
今日推荐