当前位置: 首页 > news >正文

P7915 [CSP-S 2021] 回文

题目描述

给定正整数 n n n 和整数序列 a 1 , a 2 , … , a 2 n a_1, a_2, \ldots, a_{2 n} a1,a2,,a2n,在这 2 n 2 n 2n 个数中, 1 , 2 , … , n 1, 2, \ldots, n 1,2,,n 分别各出现恰好 2 2 2 次。现在进行 2 n 2 n 2n 次操作,目标是创建一个长度同样为 2 n 2 n 2n 的序列 b 1 , b 2 , … , b 2 n b_1, b_2, \ldots, b_{2 n} b1,b2,,b2n,初始时 b b b 为空序列,每次可以进行以下两种操作之一:

  1. 将序列 a a a 的开头元素加到 b b b 的末尾,并从 a a a 中移除。
  2. 将序列 a a a 的末尾元素加到 b b b 的末尾,并从 a a a 中移除。

我们的目的是让 b b b 成为一个回文数列,即令其满足对所有 1 ≤ i ≤ n 1 \le i \le n 1in,有 b i = b 2 n + 1 − i b_i = b_{2 n + 1 - i} bi=b2n+1i。请你判断该目的是否能达成,如果可以,请输出字典序最小的操作方案,具体在【输出格式】中说明。

输入格式

每个测试点包含多组测试数据。

输入的第一行,包含一个整数 T T T,表示测试数据的组数。对于每组测试数据:

第一行,包含一个正整数 n n n
第二行,包含 2 n 2 n 2n 个用空格隔开的整数 a 1 , a 2 , … , a 2 n a_1, a_2, \ldots, a_{2 n} a1,a2,,a2n

输出格式

对每组测试数据输出一行答案。

如果无法生成出回文数列,输出一行 -1,否则输出一行一个长度为 2 n 2 n 2n 的、由字符 LR 构成的字符串(不含空格),其中 L 表示移除开头元素的操作 1,R 表示操作 2。

你需要输出所有方案对应的字符串中字典序最小的一个。

字典序的比较规则如下:长度均为 2 n 2 n 2n 的字符串 s 1 ∼ 2 n s_{1 \sim 2 n} s12n t 1 ∼ 2 n t_{1 \sim 2 n} t12n 字典序小,当且仅当存在下标 1 ≤ k ≤ 2 n 1 \le k \le 2 n 1k2n 使得对于每个 1 ≤ i < k 1 \le i < k 1i<k s i = t i s_i = t_i si=ti s k < t k s_k < t_k sk<tk

输入输出样例 #1

输入 #1

2
5
4 1 2 4 5 3 1 2 3 5
3
3 2 1 2 1 3

输出 #1

LRRLLRRRRL
-1

输入输出样例 #2

输入 #2

见附件中的 palin/palin2.in

输出 #2

见附件中的 palin/palin2.ans

说明/提示

【样例解释 #1】

在第一组数据中,生成的的 b b b 数列是 [ 4 , 5 , 3 , 1 , 2 , 2 , 1 , 3 , 5 , 4 ] [4, 5, 3, 1, 2, 2, 1, 3, 5, 4] [4,5,3,1,2,2,1,3,5,4],可以看出这是一个回文数列。

另一种可能的操作方案是 LRRLLRRRRR,但比答案方案的字典序要大。

【数据范围】

∑ n \sum n n 表示所有 T T T 组测试数据中 n n n 的和。

对所有测试点保证 1 ≤ T ≤ 100 1 \le T \le 100 1T100 1 ≤ n , ∑ n ≤ 5 × 10 5 1 \le n, \sum n \le 5 \times {10}^5 1n,n5×105

测试点编号 T ≤ T \le T n ≤ n \le n ∑ n ≤ \sum n \le n特殊性质
1 ∼ 7 1 \sim 7 17 10 10 10 10 10 10 50 50 50
8 ∼ 10 8 \sim 10 810 100 100 100 20 20 20 1000 1000 1000
11 ∼ 12 11 \sim 12 1112 100 100 100 100 100 100 1000 1000 1000
13 ∼ 15 13 \sim 15 1315 100 100 100 1000 1000 1000 25000 25000 25000
16 ∼ 17 16 \sim 17 1617 1 1 1 5 × 10 5 5 \times {10}^5 5×105 5 × 10 5 5 \times {10}^5 5×105
18 ∼ 20 18 \sim 20 1820 100 100 100 5 × 10 5 5 \times {10}^5 5×105 5 × 10 5 5 \times {10}^5 5×105
21 ∼ 25 21 \sim 25 2125 100 100 100 5 × 10 5 5 \times {10}^5 5×105 5 × 10 5 5 \times {10}^5 5×105

特殊性质:如果我们每次删除 a a a 中两个相邻且相等的数,存在一种方式将序列删空(例如 a = [ 1 , 2 , 2 , 1 ] a = [1, 2, 2, 1] a=[1,2,2,1])。

【hack 数据提供】
@潜在了H2O下面。

解题思路

  • 核心问题在于如何安排操作序列,使得 b b b 满足回文性质。关键观察如下:
  • 回文约束: b b b 的首尾必须相同,次首尾必须相同,依此类推。因此,序列 a a a 中每个数字的两次- - 出现必须被分配到 b b b 的对称位置上。
  • 操作影响:操作 L 或 R 决定了元素进入 b b b 的顺序,从而影响对称位置的配对。
  • 字典序最小:优先选择 L 操作(因为 L < R),但需保证最终能形成回文。

算法采用贪心策略:

  • 初始化配对位置:预处理序列 a a a,为每个位置 i i i 记录其配对位置 j j j(即 a i = a j a_i = a_j ai=aj i ≠ j i \neq j i=j)。
  • 尝试两种起始操作:由于字典序要求,优先尝试以 L 开头(取 a a a 的开头元素),如果失败再尝试- - 以 R 开头(取 a a a 的末尾元素)。
  • 模拟匹配过程:基于起始操作,将剩余位置划分为两个队列(左队列和右队列),然后贪心地匹配位置对:
  • 每次检查队列两端的四种可能匹配:左队首 vs 左队尾、左队首 vs 右队尾、右队首 vs 左队尾、右队首 vs 右队尾。
  • 如果匹配成功(即两位置的数字相同),记录操作并更新队列;优先选择能产生 L 操作的匹配以保持字典序最小。
  • 构建操作序列:匹配过程中记录前半部分操作(xian)和后半部分操作(ho),最终输出为 xian 顺序加上 ho 逆序。

算法正确性

  • 回文保证:匹配过程确保每个数字的两次出现被分配到对称位置,从而 b b b 满足 b i = b 2 n + 1 − i b_i = b_{2n+1-i} bi=b2n+1i
  • 字典序最小:优先尝试 L 开头,且在匹配中优先选择 L 操作(对应 xian 添加 L)。如果 L 开头可行,直接输出;否则尝试 R 开头,但需保证输出方案是所有可行方案中字典序最小的。
  • 可行性判断:如果两种起始操作均失败,则输出 -1。
  • 复杂度分析
  • 时间复杂度:每组数据时间复杂度为 O ( n ) O(n) O(n)。预处理配对位置 O ( n ) O(n) O(n),匹配过程每个元素处理一次 O ( n ) O(n) O(n)。总时间复杂度 O ( ∑ n ) O(\sum n) O(n),满足数据范围 ∑ n ≤ 5 × 1 0 5 \sum n \le 5 \times 10^5 n5×105
  • 空间复杂度: O ( n ) O(n) O(n),用于存储序列、配对位置和队列。

代码实现解析

  • 以下是基于题目所给代码的关键步骤解释(代码已优化):
  • 预处理配对:使用数组 zhiqianshu 记录数字首次出现的位置,duiyinweizhi[i] 存储位置 i i i 的配对位置。
  • 起始操作尝试:调用 solve(‘L’) 优先尝试 L 开头;若失败,再调用 solve(‘R’)。
  • 匹配模拟:
  • 根据起始操作初始化左队列(剩余位置的开头部分)和右队列(剩余位置的末尾部分)。
  • 循环检查队列两端的四种匹配:
  • 若左队首与左队尾匹配,添加两个 L 操作(记录到 xian 和 ho)。
  • 若左队首与右队尾匹配,添加 L(xian)和 R(ho)。
  • 若右队首与左队尾匹配,添加 R(xian)和 L(ho)。
  • 若右队首与右队尾匹配,添加两个 R 操作(记录到 xian 和 ho)。
  • 若无法匹配,返回失败。
  • 输出操作序列:顺序输出 xian 中的操作,逆序输出 ho 中的操作(确保整体操作序列正确)。

示例分析

  • 以样例输入 n = 5 n=5 n=5 a = [ 4 , 1 , 2 , 4 , 5 , 3 , 1 , 2 , 3 , 5 ] a = [4, 1, 2, 4, 5, 3, 1, 2, 3, 5] a=[4,1,2,4,5,3,1,2,3,5] 为例:

  • 预处理配对:位置 1 1 1 4 4 4 均为 4 4 4,位置 2 2 2 7 7 7 均为 1 1 1,依此类推。

  • 起始操作 L:取 a [ 1 ] = 4 a[1] = 4 a[1]=4,配对位置为 4 4 4。剩余位置划分为左队列 [ 2 , 3 ] [2, 3] [2,3]、右队列 [ 10 , 9 , 8 , 7 , 6 , 5 ] [10, 9, 8, 7, 6, 5] [10,9,8,7,6,5]

  • 匹配过程:

  • 左队首 2 2 2 a [ 2 ] = 1 a[2]=1 a[2]=1)与右队尾 5 5 5 a [ 5 ] = 5 a[5]=5 a[5]=5)不匹配;但左队首 2 2 2 与右队尾 7 7 7 a [ 7 ] = 1 a[7]=1 a[7]=1)匹配,添加 L(xian)和 R(ho)。

  • 更新队列后,继续匹配,最终得到 xian = [‘L’, ‘R’, ‘R’, ‘L’, ‘L’],ho = [‘R’, ‘R’, ‘R’, ‘R’, ‘L’]。

  • 输出序列:xian 顺序输出 “LRRLL”,ho 逆序输出 “RRRRL”(即 “LRRLL” + “RRRRL” = “LRRLLRRRRL”)。

  • 对于 n = 3 n=3 n=3 a = [ 3 , 2 , 1 , 2 , 1 , 3 ] a = [3, 2, 1, 2, 1, 3] a=[3,2,1,2,1,3]

  • 尝试 L 开头(取 a [ 1 ] = 3 a[1]=3 a[1]=3,配对位置 6 6 6),但剩余位置无法完成匹配。

  • 尝试 R 开头(取 a [ 6 ] = 3 a[6]=3 a[6]=3,配对位置 1 1 1),剩余位置仍无法匹配,输出 -1。

详细代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+5;
int a[N*2],zhiqianshu[N*2],duiyinweizhi[N*2],n;
bool solve(char cc)
{deque<int>zuokuohao,youkuohao;vector<int>xian,ho;xian.push_back(cc=='L'?0:6);ho.push_back(0);if (cc=='L'){for(int i=2;i<duiyinweizhi[1];i++) zuokuohao.push_back(i);for(int i=n;i>duiyinweizhi[1];i--) youkuohao.push_back(i);} else{for(int i=1;i<duiyinweizhi[n];i++) zuokuohao.push_back(i);for(int i=n-1;i>duiyinweizhi[n];i--) youkuohao.push_back(i);}while(zuokuohao.size()>0||youkuohao.size()>0){int x1=zuokuohao.size()?zuokuohao.front():0;int x2=youkuohao.size()?youkuohao.front():0;int y1=zuokuohao.size()?zuokuohao.back():0;int y2=youkuohao.size()?youkuohao.back():0;if(duiyinweizhi[x1]==y1){xian.push_back(0);ho.push_back(0);zuokuohao.pop_front();zuokuohao.pop_back();}else if(duiyinweizhi[x1]==y2){xian.push_back(0);ho.push_back(6);zuokuohao.pop_front();youkuohao.pop_back();}else if(duiyinweizhi[x2]==y1){xian.push_back(6);ho.push_back(0);youkuohao.pop_front();zuokuohao.pop_back();}else if(duiyinweizhi[x2]==y2) {xian.push_back(6);ho.push_back(6);youkuohao.pop_front();youkuohao.pop_back();} elsereturn false;}for(vector<int>::iterator it=xian.begin();it!=xian.end();it++)cout<<char('L'+*it);for(vector<int>::reverse_iterator it=ho.rbegin();it!=ho.rend();it++)cout<<char('L'+*it);cout<<'\n';return true;
}
signed main()
{	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);int _;cin>>_;while (_--){cin>>n;memset(zhiqianshu,0,sizeof(zhiqianshu));n*=2;duiyinweizhi[0]=-1;for (int i=1;i<=n;i++){cin>>a[i];if(zhiqianshu[a[i]]){duiyinweizhi[zhiqianshu[a[i]]]=i;duiyinweizhi[i]=zhiqianshu[a[i]];}elsezhiqianshu[a[i]]=i;}if(!solve('L')&&!solve('R'))cout<<"-1"<<'\n';}return 0;
}

相关文章:

  • 网站建设怎么说服客户下载百度卫星导航
  • 镇江网站制作哪家好口碑营销案例ppt
  • 网站测试设计历下区百度seo
  • vb语言做的网站苏州百度推广开户
  • b2c平台网站建设专业做seo推广
  • 网站建设考核标准北京网站快速优化排名
  • Sortablejs动态同类型穿插
  • 基于大数据的社会治理与决策支持方案PPT(66页)
  • 基于开源AI大模型、AI智能名片与S2B2C商城小程序的美食菜单社交化营销创新研究
  • DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_服药提醒示例(CalendarView01_24)
  • 深度学习在智能零售中的创新应用与未来趋势
  • web安全之h2注入系统学习
  • 鸿蒙开发中的多媒体与硬件集成深度解析
  • 【案例】基于Python的生源数据可视化分析:从Excel处理到动态地图展示
  • Kylin Linux Advanced Server V10 离线安装 Prometheus + Grafana + node_exporter指南
  • 解决 tmux 中 Conda 环境不生效的问题(附自动继承配置)
  • Python虚拟环境管理:conda、venv、pipenv三国杀
  • LE AUDIO---Chapter 2. The Bluetooth® LE Audio architecture
  • 在 Logstash 中使用 Ruby 脚本
  • 使用redis服务的redisson架构实现分布式锁
  • Prompt:面向目标的提示词
  • Web 点播播放器如何加载缩略图?
  • SQL关键字三分钟入门:DELETE —— 删除数据
  • js 组装树形结构
  • Mac安装Apache CXF的时候报错:/Library/Internet: No such file or directory
  • Windows下Zookeeper客户端启动缓慢问题分析与解决方案