1 条题解

  • 0
    @ 2026-5-14 14:14:32

    题目理解

    我们有一个数组 aa,长度 nn
    对每个下标 ii1i<n1 \le i < n),可以最多执行一次操作:
    aia_i 赋值为 aiai+1a_i \oplus a_{i+1}\oplus 表示按位异或)。
    目标:判断是否能将 aa 变成目标数组 bb


    关键观察

    每个位置 ii 的值最多改变一次
    因为操作只允许对每个 ii 最多执行一次,且操作只修改 aia_i 的值(不修改 ai+1a_{i+1})。
    因此,在整个过程中:

    • 要么 aia_i 保持原来的值
    • 要么 aia_i 在某一时刻被赋值为 aiai+1a_i \oplus a_{i+1}(原始值或 bi+1b_{i+1} 取决于操作顺序)

    但注意:ai+1a_{i+1} 也可能被之前的操作改变(如果 i+1i+1 位置被操作过)。
    所以更准确地说:
    当考虑位置 ii 时,ai+1a_{i+1} 的值可能是原始 ai+1a_{i+1},也可能是 bi+1b_{i+1}(因为 i+1i+1 的操作只可能发生在 ii 之前或之后)。


    从后向前贪心

    因为操作只影响 aia_i,不影响 ai+1a_{i+1}ai+1a_{i+1} 只被它自己的操作影响),我们可以从后向前处理。

    固定最后一个位置
    ana_n 永远不会被任何操作修改(因为没有 an+1a_{n+1} 与其做异或)。
    因此 必须 an=bna_n = b_n,否则直接不可能。

    考虑位置 ii(从 n1n-1 向下到 11

    我们已知 ai+1a_{i+1} 的最终值就是 bi+1b_{i+1}(因为后面的已经处理好了)。
    现在 aia_i 的最终值要变成 bib_i
    aia_i 可能的情况:

    1. 没有对 ii 执行操作 \Rightarrow 必须 ai=bia_i = b_i
    2. ii 执行了操作,此时 aia_i 变为 aiai+1a_i \oplus a_{i+1}
      ai+1a_{i+1} 在操作时的值可能是原始值 ai+1a_{i+1}(如果 i+1i+1 还没被操作)或 bi+1b_{i+1}(如果 i+1i+1 已经被操作过)。
      所以有两种可能:
      • 如果 i+1i+1 没有ii 之前被操作,那么 aia_i 变成 aiai+1=bia_i \oplus a_{i+1} = b_i
      • 如果 i+1i+1 ii 之前被操作了,那么 aia_i 变成 aibi+1=bia_i \oplus b_{i+1} = b_i

    因此,位置 ii 可行的条件为(三者至少一个成立):

    • ai=bia_i = b_i(不操作)
    • aiai+1=bia_i \oplus a_{i+1} = b_i(先操作 ii,后操作 i+1i+1 或不操作 i+1i+1
    • aibi+1=bia_i \oplus b_{i+1} = b_i(先操作 i+1i+1,再操作 ii

    依赖关系与可行性

    这三种情况本质上定义了 iii+1i+1 的操作顺序依赖:

    • 如果 ai=bia_i = b_i,则 ii 不操作,无依赖。
    • 如果 aiai+1=bia_i \oplus a_{i+1} = b_i,则必须 先操作 ii(若 i+1i+1 也会被操作,必须晚于 ii)。
    • 如果 aibi+1=bia_i \oplus b_{i+1} = b_i,则必须 先操作 i+1i+1(若两者都操作,必须早于 ii)。

    注意:ai+1a_{i+1} 可能被操作,也可能不被操作。
    由于所有依赖都是相邻点之间的,这种依赖图一定无环(因为边只会从 ii 指向 i+1i+1 或反向)。
    因此只要每个 ii 满足至少一个条件,就存在一种全局顺序,使得所有要求满足。


    最终算法

    1. 检查 anbna_n \ne b_n,若不等则输出 "NO"
    2. i=n1i = n-1 向下到 11
      • 检查以下三个条件是否至少一个为真:
        • ai=bia_i = b_i
        • aiai+1=bia_i \oplus a_{i+1} = b_i
        • aibi+1=bia_i \oplus b_{i+1} = b_i
      • 若都不成立,输出 "NO"
    3. 全部通过则输出 "YES"

    复杂度 O(n)O(n) 每个测试用例。


    示例验证

    以第一个样例:

    • a=[1,2,3,4,5],b=[3,2,7,1,5]a = [1,2,3,4,5], b = [3,2,7,1,5]
    • i=4:a4=4,b4=1,a5=5,b5=5i=4: a_4=4, b_4=1, a_5=5, b_5=5
      检查:414 \ne 145=14\oplus5=1 ✓ 通过
    • i=3:a3=3,b3=7,a4=4,b4=1i=3: a_3=3, b_3=7, a_4=4, b_4=1
      检查:373\ne734=73\oplus4=7 ✓ 通过
    • i=2:a2=2,b2=2i=2: a_2=2, b_2=2 ✓ 通过
    • i=1:a1=1,b1=3,a2=2,b2=2i=1: a_1=1, b_1=3, a_2=2, b_2=2
      检查:131\ne312=31\oplus2=3 ✓ 通过
    • 结果 "YES"

    C++ 实现

    #include <bits/stdc++.h>
    using namespace std;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        
        int t;
        cin >> t;
        while (t--) {
            int n;
            cin >> n;
            vector<int> a(n), b(n);
            for (int i = 0; i < n; i++) cin >> a[i];
            for (int i = 0; i < n; i++) cin >> b[i];
            
            bool ok = true;
            if (a.back() != b.back()) {
                ok = false;
            }
            
            for (int i = n - 2; i >= 0 && ok; i--) {
                if (a[i] == b[i]) continue;
                if ((a[i] ^ a[i + 1]) == b[i]) continue;
                if ((a[i] ^ b[i + 1]) == b[i]) continue;
                ok = false;
            }
            
            cout << (ok ? "YES" : "NO") << '\n';
        }
        
        return 0;
    }
    
    • 1

    信息

    ID
    7045
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    1
    已通过
    1
    上传者