洛谷P7915 回文

题目描述

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

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

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

输入格式

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

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

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

输出格式

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

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

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

字典序的比较规则如下:长度均为 2 n2n 的字符串 s_{1 \sim 2 n}s1∼2n​ 比 t_{1 \sim 2 n}t1∼2n​ 字典序小,当且仅当存在下标 1 \le k \le 2 n1≤k≤2n 使得对于每个 1 \le i < k1≤i<k 有 s_i = t_isi​=ti​ 且 s_k < t_ksk​<tk​。

输入输出样例

输入 #1复制

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

输出 #1复制

LRRLLRRRRL
-1

说明/提示

【样例解释 #1】

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

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

【数据范围】

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

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

测试点编号T \leT≤n \len≤\sum n \le∑n≤特殊性质
1 \sim 71∼7101010105050
8 \sim 108∼10100100202010001000
11 \sim 1211∼1210010010010010001000
13 \sim 1513∼15100100100010002500025000
16 \sim 1716∼17115 \times {10}^55×1055 \times {10}^55×105
18 \sim 2018∼201001005 \times {10}^55×1055 \times {10}^55×105
21 \sim 2521∼251001005 \times {10}^55×1055 \times {10}^55×105

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

上代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mo=1e9+7;
inline int read(){
	char ch=getchar();int x=0, f=1;
	while(!isdigit(ch)) f=(ch=='-'?-1:f), ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0', ch=getchar();
	return x*f; 
}
const int N=5e5+5;
int n, L[N], R[N], a[2*N], b[2*N];
char ans[2*N];
bool doit(int lst, int Li, int Ri){
	if(Li==2) ans[1]='L';
	else ans[1]='R';
	int l=lst, r=lst, st=2, ed=2*n-1;
	for(int i=1; i<n; i++){
		if(R[a[Li]]==l-1) l--, Li++, ans[st++]='L', ans[ed--]='L';
		else if(R[a[Li]]==r+1) r++, Li++, ans[st++]='L', ans[ed--]='R';
		else if(L[a[Ri]]==l-1) l--, Ri--, ans[st++]='R', ans[ed--]='L';
		else if(L[a[Ri]]==r+1) r++, Ri--, ans[st++]='R', ans[ed--]='R';
		else return 0;
	}
	ans[2*n]='L';printf("%s\n", ans+1);return 1;
}
void solve(){
	memset(L, 0, sizeof(L));
	memset(R, 0, sizeof(R));
	memset(b, 0, sizeof(0));
	memset(ans, 0, sizeof(ans));
	n=read();for(int i=1; i<=2*n; i++)
	a[i]=read(), L[a[i]]?R[a[i]]=i:L[a[i]]=i;
	if(doit(R[a[1]], 2, 2*n)) return ;
	if(doit(L[a[2*n]], 1, 2*n-1)) return ;
	puts("-1");return ;
}
signed main(){
	int T=read();while(T--) solve();
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值