CF2115B Gellyfish and Camellia Japonica

题目大意

对与一个长度为 \(n\) 的数组 \(c\)(我们称数组中第 \(i\) 个数为 \(c_i\)),要进行 \(q\) 次修改操作(第 \(i\) 次修改,由三个整数 \(x_i, y_i, z_i\) 描述,将 \(c_{z_i}\) 修改为 \(\min(c_{x_i},c_{y_i})\)),问:给出操作后的数组以及 \(q\) 次操作,还原可能的数组,若不能还原,输出 -1

分析

看到题目,\(n \leq 3 \times 10^5\),猜测是 \(O(n)\) 的时间复杂度。

然后,我们容易发现,正着做很难实现,我们尝试倒过来(这是一个经典套路)。

在继续看题,我们可以知道 \(c_{z_i} \leq c_{x_i}\) 同时 \(c_{z_i} \leq c_{y_i}\),假设我们倒着做,容易想到 \(c_{x_i}\)\(c_{y_i}\) 最少也只能是 \(c_{z_i}\)。根据这个,我们就可以倒着覆盖它,令 \(c_{x_i} = \max(c_{x_i}, c_{z_i})\)\(c_{y_i}\) 同理。

至于能否合法,发现不能在计算过程中得出,我们就暴力正着对答案操作,看结果是否与输入数组相同,不同则无解。

此时,你可以过样例了,但是会答案错误!为什么呢?因为在 \(z_i\)\(x_i\)\(y_i\) 的情况下,你是不可以直接确定它的答案的,它可能会与后面某些操作取最大值,导致答案错误。解决这个问题,我们可以直接将它赋值为 \(0\)。这样若造成该种情况也可以复原,同时不影响答案。

最后简单实现一下就好了!

差点场切了,但是因为上面的情况没考虑到,少了两句话,然后答案错误了。

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 3e5 + 7;

int n, q, b[MAXN], c[MAXN], d[MAXN];

struct node {
    int x, y, z;
} g[MAXN];

signed main()
{
    int T;

    scanf("%d", &T);

    while(T--)
    {
        scanf("%d %d", &n, &q);
        
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &b[i]);
            c[i] = b[i];
        }

        int flag = 0;

        for(int i = 1; i <= q; i++)
            scanf("%d %d %d", &g[i].x, &g[i].y, &g[i].z);

        for(int i = q; i >= 1; i--)
        {
            int val = c[g[i].z];
            c[g[i].z] = 0;
            c[g[i].x] = max(c[g[i].x], val);
            c[g[i].y] = max(c[g[i].y], val);
            // 错误的打法(我赛时没考虑的)
            // c[g[i].x] = max(c[g[i].x], c[g[i].z]);
            // c[g[i].y] = max(c[g[i].y], c[g[i].z]);
        }

        for(int i = 1; i <= n; i++)
            d[i] = c[i];

        for(int i = 1; i <= q; i++)
            d[g[i].z] = min(d[g[i].x], d[g[i].y]);
        
        for(int i = 1; i <= n; i++)
        {
            if(d[i] != b[i])
            {
                flag = 1;
                break;
            }
        }

        if(flag)
        {
            puts("-1");
            continue ;
        }

        for(int i = 1; i <= n; i++)
            printf("%d ",c[i]);
        puts("");
    }

    return 0;
}
posted @ 2026-01-04 11:30  HHMing  阅读(1)  评论(0)    收藏  举报