1 条题解

  • 0
    @ 2026-10-27 1:47:48

    思路与算法

    先尝试首步L,失败再尝试R。首个数的另一次出现必须是回文最后一项,暂时固定该位置。剩余数组被它分为左右两段,分别用双端指针表示。同步构造回文前后两端:前半步只能从两段外端取,配对的后半步只能从两段内端取;比较四种端点配对,优先选择前半步为L的合法项,写入对称操作。最后一个元素只有一种取值,操作选L。

    正确性说明

    每个数只出现两次,因此指定前半步后,其配对位置唯一;只有该位置已经处在某段内端,才可能成为对应的倒序后半步。端点相等时移除这一对保持两段不变式。若左右外端相等而无法与内端配对,它们都应在此前固定最后元素之前被取走,不能互作最终配对,所以不是一个被遗漏的选择。对同一前半步无两个不同配对位置;若L、R均合法,先完成L配对可与可行方案的对称取对次序交换,不影响各段端点顺序,字典序更优。归纳得到每个首步下的最小方案;L首步优先给全局最小,两者都失败才无解。

    复杂度

    每组O(n)时间、O(n)空间,含双端区间、答案字符串初始化;至多两次尝试,总O(∑n)。

    易错点

    字典序要求真实L<R;最终单元素取L。不能只输出任意回文操作;-1使用半角负号。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    
    string solve(const vector<int> &a, bool right) {
        int N = a.size(), n = N / 2, start = right ? N - 1 : 0, p = -1;
        for (int i = 0; i < N; i++)
            if (i != start && a[i] == a[start])
                p = i;
        int l = right ? 0 : 1, r = p - 1, L = p + 1, R = right ? N - 2 : N - 1;
        string ans(N, 'L');
        ans[0] = right ? 'R' : 'L';
        for (int i = 1; i < n; i++) {
            if (l < r && a[l] == a[r]) {
                ans[i] = 'L';
                ans[N - 1 - i] = 'L';
                l++;
                r--;
            } else if (l <= r && L <= R && a[l] == a[L]) {
                ans[i] = 'L';
                ans[N - 1 - i] = 'R';
                l++;
                L++;
            } else if (l <= r && L <= R && a[R] == a[r]) {
                ans[i] = 'R';
                ans[N - 1 - i] = 'L';
                R--;
                r--;
            } else if (L < R && a[R] == a[L]) {
                ans[i] = 'R';
                ans[N - 1 - i] = 'R';
                R--;
                L++;
            } else
                return "";
        }
        return ans;
    }
    int main() {
        int T;
        cin >> T;
        while (T--) {
            int n;
            cin >> n;
            vector<int> a(2 * n);
            for (int &x : a)
                cin >> x;
            string ans = solve(a, false);
            if (ans.empty())
                ans = solve(a, true);
            cout << (ans.empty() ? "-1" : ans) << "\n";
        }
    }
    
    • 1

    信息

    ID
    1973
    时间
    1000ms
    内存
    512MiB
    难度
    普及+
    标签
    递交数
    0
    已通过
    0
    上传者