[CSP-S2021] 回文
链接:
题意:
给出一个长度为 \(2n\) 的序列 \(a\),其中 \(1\sim n\) 每个数出现了 2 次。有 L,R 两种操作分别是将 \(a\) 的开头或末尾元素加入到初始为空的序列 \(b\) 里,目标是让 \(b\) 成为一个回文串。
需要判断无解或求出字典序最小的方案。
\(T(T\leq100)\) 组数据,对于每组数据 \(n\leq5\times10^5\)。\(\sum n\leq5\times10^5\)。
分析:
首先对于 \(a\) 串,一定存在一个分界点使得左边的元素是通过 L 操作弹出的,右边的元素是通过 R 操作弹出的,显然 \(b\) 的末尾就在这个分界点的两边,显然 \(b\) 的末尾一定是 \(a\) 的开头或结尾,这里先假设是开头。
那么找到这个分界点,也就是与 \(a_1\) 相同的位置。发现序列被分成了两段,左边一段是从左往右通过 L 操作弹出的,右边一段是从右往左通过 R 操作弹出的,那么我们把这两段拉出来,这里有个细节就是分界点要分在左边一段,因为要求字典序最小。
假设与 \(a_1\) 相等的地方是 \(i\),\(i\) 的下一个位置是 \(j\),大概就是:

变成了两个队列,队首在 \(b\) 的前面,队尾在 \(b\) 的后面,那么只要队首和队尾能配对,就贪心选择字典序小的并加入到 \(b\) 里就可以了。
然后如果 \(b\) 的末尾是 \(a\) 的末尾,就重新找分界点再做一遍就行了。
另外,可能会存在 \(a\) 的开头等于 \(a\) 的末尾的情况,此时除非原始串就是回文串,否则是无解的,特判一下就行了。
算法:
找到分界点,维护两个双端队列,贪心选择即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
inline int read(){
int p=0,f=1;
char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){p=p*10+c-'0';c=getchar();}
return p*f;
}
const int N=5e5+5;
int T,n,a[N<<1];
int flag,s,e;
int A[N<<1],ai,an;
int B[N<<1],bi,bn;
int ans[N<<1];
signed main(){
freopen("palin.in","r",stdin);
freopen("palin.out","w",stdout);
T=in;
while(T--){
flag=1;n=in;
for(int i=1;i<=(n<<1);i++)a[i]=in;
for(int i=1;i<=n;i++)
if(a[i]!=a[(n<<1)-i+1])flag=0;
for(int i=2;i<(n<<1);i++){
if(a[i]==a[1])s=i;
if(a[i]==a[(n<<1)])e=i;
}
if(a[1]==a[(n<<1)]){
if(flag){for(int i=1;i<=(n<<1);i++)putchar('L');puts("");}
else puts("-1");
continue;
}
for(int i=1;i<=s;i++)A[i]=a[i];an=s;bn=(n<<1)-s;
for(int i=(n<<1);i>=s+1;i--)B[(n<<1)-i+1]=a[i];
ai=1,bi=1,flag=0;
for(int i=1;i<=n;i++){
if(ai<an&&A[ai]==A[an])
ans[i]=ans[(n<<1)-i+1]='L',ai++,an--;
else if(ai<=an&&bi<=bn&&A[ai]==B[bn])
ans[i]='L',ans[(n<<1)-i+1]='R',ai++,bn--;
else if(bi<bn&&B[bi]==B[bn])
ans[i]=ans[(n<<1)-i+1]='R',bi++,bn--;
else if(ai<=an&&bi<=bn&&B[bi]==A[an])
ans[i]='R',ans[(n<<1)-i+1]='L',bi++,an--;
else flag=1;
}
if(!flag){
for(int i=1;i<=(n<<1);i++)
cout<<(char)ans[i];
puts("");
}
else{
s=e;
for(int i=1;i<=s;i++)A[i]=a[i];an=s;bn=(n<<1)-s;
for(int i=(n<<1);i>=s+1;i--)B[(n<<1)-i+1]=a[i];
ai=1,bi=1,flag=0;
for(int i=1;i<=n;i++){
if(ai<an&&A[ai]==A[an])
ans[i]=ans[(n<<1)-i+1]='L',ai++,an--;
else if(ai<=an&&bi<=bn&&A[ai]==B[bn])
ans[i]='L',ans[(n<<1)-i+1]='R',ai++,bn--;
else if(bi<bn&&B[bi]==B[bn])
ans[i]=ans[(n<<1)-i+1]='R',bi++,bn--;
else if(ai<=an&&bi<=bn&&B[bi]==A[an])
ans[i]='R',ans[(n<<1)-i+1]='L',bi++,an--;
else flag=1;
}
if(!flag){
for(int i=1;i<=(n<<1);i++)
cout<<(char)ans[i];
puts("");
}
else puts("-1");
}
}
return 0;
}
题外话:
没想到会这么简单,失策了
[CSP-S2021] 回文的更多相关文章
- LeetCode[5] 最长的回文子串
题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- 最长回文子串-LeetCode 5 Longest Palindromic Substring
题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- [LeetCode] Longest Palindrome 最长回文串
Given a string which consists of lowercase or uppercase letters, find the length of the longest pali ...
- [LeetCode] Palindrome Pairs 回文对
Given a list of unique words. Find all pairs of distinct indices (i, j) in the given list, so that t ...
- [LeetCode] Palindrome Permutation II 回文全排列之二
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...
- [LeetCode] Palindrome Permutation 回文全排列
Given a string, determine if a permutation of the string could form a palindrome. For example," ...
- [LeetCode] Palindrome Linked List 回文链表
Given a singly linked list, determine if it is a palindrome. Follow up: Could you do it in O(n) time ...
- [LeetCode] Shortest Palindrome 最短回文串
Given a string S, you are allowed to convert it to a palindrome by adding characters in front of it. ...
- [LeetCode] Palindrome Partitioning II 拆分回文串之二
Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...
- [LeetCode] Palindrome Partitioning 拆分回文串
Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...
随机推荐
- Apache配置与应用
目录: 一.基于域名的虚拟主机 二.基于IP地址的虚拟主机 三.基于端口的虚拟主机 四.Apache连接保持 五.构建Web虚拟目录与用户授权限制 六.Apache日志分割 七.AWStats 分析系 ...
- Jmeter扩展组件开发(3) - 实现方法
继承JavaSamplerClient,四种实现方法讲解 前提 JavaSamplerClient要把四种实现方法都继承,编译器才不会报错. com.demo(package包)右键新建一个secon ...
- javascript 字符串反转 strip_tags 字符串常用的自定义函数,加载css etc.
字符串反转 String.prototype.reverse = function() { var a = this.split(''); for (var i = 0, j = a.length-1 ...
- AVS 端能力之蓝牙模块
该类为蓝牙端能力处理类,主要负责蓝牙设备配对和蓝牙音频播放功能. 功能简介 实现蓝牙设备的启动发现模式.扫描蓝牙设备.建立蓝牙连接功能 实现蓝牙设备音频播放.停止.上一首.下一首功能 其它细节参考&l ...
- P3507-[POI2010]GRA-The Minima Game【dp,博弈论】
正题 题目链接:https://www.luogu.com.cn/problem/P3507 题目大意 \(n\)个数,没人轮流取若干个并获得取走的数中最小数的权值,两人的目标都是自己的权值\(-\) ...
- CF786C-Till I Collapse【树状数组倍增,优先队列】
正题 题目链接:https://www.luogu.com.cn/problem/CF786C 题目大意 给出一个长度为\(n\)的序列. 对于每个\(k\in[1,n]\)求将\(n\)分成最少的段 ...
- Skywalking-09:OAL原理——如何通过动态生成的Class类保存数据
OAL 如何通过动态生成的 Class 类,保存数据 前置工作 OAL 如何将动态生成的 SourceDispatcher 添加到 DispatcherManager // org.apache.sk ...
- Spring Boot 整合单机websocket(附github源码)
websocket 概念 websocket 是一个通信协议,通过单个 TCP 连接提供全双工通信.websocket 连接成功后,服务端和客户可以进行双向通信.不同于 http 通信协议需要每次由客 ...
- PHP审计之PHP反序列化漏洞
PHP审计之PHP反序列化漏洞 前言 一直不懂,PHP反序列化感觉上比Java的反序列化难上不少.但归根结底还是serialize和unserialize中的一些问题. 在此不做多的介绍. 魔术方法 ...
- 记录一次基于VuePress + Github 搭建个人博客
最终效果图 网站:https://chandler712.github.io/ 一.前言 VuePress 是尤雨溪推出的支持 Vue 及其子项目的文档需求而写的一个项目,UI简洁大方,官方文档详细容 ...