[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 ...
随机推荐
- CUDA 矩阵乘法终极优化指南
作者:马骏 | 旷视 MegEngine 架构师 前言 单精度矩阵乘法(SGEMM)几乎是每一位学习 CUDA 的同学绕不开的案例,这个经典的计算密集型案例可以很好地展示 GPU 编程中常用的优化技巧 ...
- etcd学习(10)-etcd对比Consul和zooKeeper如何选型
etcd选型对比 前言 基本架构和原理 etcd Consul ZooKeeper 选型对比 总结 参考 etcd选型对比 前言 对比 Consul, ZooKeeper.选型etcd有那些好处呢? ...
- Java学习笔记--常用容器
容器 1. 出现原因 解决程序运行时需要创建新对象,在程序运行前不知道运行的所需的对象数量甚至是类型的问题. Java中提供了一套集合类来解决这些问题包括:List.Set.Queue.Map 2. ...
- golang中的闭包_closure
闭包_Closure: 1.一般情况下,第一类对象都是独立的封闭的存在的,独立的封闭的起作用; 2.第一类对象可以被创建; 3.第一类对象可以作为参数传递给其他函数; 4.第一类对象可以赋值给变量实体 ...
- 在vue-cli项目中定义全局 filter、method 方法
1.创建 filters.js(methods.js) 文件: 2.filters.js(methos.js) 中定义全局过滤方法: 1 export default { 2 /** 时间戳转换 */ ...
- 机器学*——K*邻算法(KNN)
1 前言 Kjin邻法(k-nearest neighbors,KNN)是一种基本的机器学*方法,采用类似"物以类聚,人以群分"的思想.比如,判断一个人的人品,只需观察他来往最密切 ...
- scrum项目冲刺_day04总结
摘要:今日完成任务. 1.图像识别已优化 2.语音识别正在进行 3.搜索功能 正在进行 总任务: 一.appUI页面(已完成) 二.首页功能: 1.图像识别功能(已完成) 2.语音识别功能 3.垃圾搜 ...
- 微信小程序+腾讯云直播的实时音视频实战笔记
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- final关键字在PHP中的使用
final关键字的使用非常简单,在PHP中的最主要作用是定义不可重写的方法.什么叫不可重写的方法呢?就是子类继承后也不能重新再定义这个同名的方法. class A { final function t ...
- 解决navicat 导出excel数字为科学计数法问题
1.原因分析 用程序导出的csv文件,当字段中有比较长的数字字段存在时,在用excel软件查看csv文件时就会变成科学技术法的表现形式. 其实这个问题跟用什么语言导出csv文件没有关 ...