[CSP-S 2021] 回文 题解
题目大意
给定正整数 和整数序列 ,在这 个数中, 分别各出现恰好 次。现在进行 次操作,目标是创建一个长度同样为 的序列 ,初始时 为空序列,每次可以进行以下两种操作之一:
将序列 的开头元素加到 的末尾,并从 中移除。
将序列 的末尾元素加到 的末尾,并从 中移除。
我们的目的是让 成为一个回文数列。请你判断该目的是否能达成,如果可以,请输出字典序最小的操作方案(其中第一个操作输出 L
,第二个输出 R
),否则输出 -1
。
题目解析
用样例一的第一组数据来说明做法。
考虑第一个先选择操作 (其实先选择操作 是一样的,当然我们优先选择操作 ),也就是把 到 序列后面。
此时我们发现这时我们需要保证在最后让序列 只剩下一个数字 。
也就是说序列 会被分成两半: 和
这时我们如果继续取,那么就必须要在里面两端有相同的数字这样在最后取的时候才能构成回文串。当然我们优先从左边取。如果左右都不满足就代表这样是无解的,需要尝试另一种方法。
最后注意一下序列不能为空。
代码采用双端队列的方法来实现。
#include<cstdio> #define db double #define gc getchar #define pc putchar #define U unsigned #define ll long long #define ld long double #define ull unsigned long long #define Tp template<typename _T> #define Me(a,b) memset(a,b,sizeof(a)) Tp _T mabs(_T a){ return a>0?a:-a; } Tp _T mmax(_T a,_T b){ return a>b?a:b; } Tp _T mmin(_T a,_T b){ return a<b?a:b; } Tp void mswap(_T &a,_T &b){ _T tmp=a; a=b; b=tmp; return; } Tp void print(_T x){ if(x<0) pc('-'),x=-x; if(x>9) print(x/10); pc((x%10)+48); return; } #define EPS (1e-7) #define INF (0x7fffffff) #define LL_INF (0x7fffffffffffffff) #define maxn 1000039 #define maxm #define MOD #define Type int #ifndef ONLINE_JUDGE //#define debug #endif using namespace std; Type read(){ char c=gc(); Type s=0; int flag=0; while((c<'0'||c>'9')&&c!='-') c=gc(); if(c=='-') c=gc(),flag=1; while('0'<=c&&c<='9'){ s=(s<<1)+(s<<3)+(c^48); c=gc(); } if(flag) return -s; return s; } int n,nn,a[maxn],b[maxn],ans[maxn];//0l1r int s1[maxn],s2[maxn],top1,top2,bot1,bot2,p; int solve(){ int i; for(i=2;i<=n;i++){ if(top1-1>=bot1&&s1[top1]==s1[bot1]){ ans[i]=0; bot1++; top1--; } else if(top1>=bot1&&top2>=bot2&&s1[top1]==s2[bot2]){ ans[i]=0; bot2++; top1--; } else if(top2-1>=bot2&&s2[top2]==s2[bot2]){ ans[i]=1; bot2++; top2--; } else if(top1>=bot1&&top2>=bot2&&s2[top2]==s1[bot1]){ ans[i]=1; bot1++; top2--; } else return 0; } return 1; } int check1(){ p=1; ans[1]=0; int i,tmp; top1=top2=0; bot1=bot2=1; for(i=2;i<=nn;i++) if(a[i]==a[1]) tmp=i; for(i=tmp-1;i>1;i--) s1[++top1]=a[i]; for(i=tmp+1;i<=nn;i++) s2[++top2]=a[i]; return solve(); } int check2(){ p=1; ans[1]=1; int i,tmp; top1=top2=0; bot1=bot2=1; for(i=1;i<nn;i++) if(a[i]==a[nn]) tmp=i; for(i=tmp-1;i>=1;i--) s1[++top1]=a[i]; for(i=tmp+1;i<nn;i++) s2[++top2]=a[i]; top1=tmp-1; top2=nn-tmp-1; return solve(); } void printans(){ int pl=1,pr=nn,i; for(i=1;i<=n;i++) if(!ans[i]) b[i]=a[pl++]; else b[i]=a[pr--]; for(i=n+1;i<=nn;i++) if(a[pl]==b[nn-i+1]) ans[i]=0,pl++; else ans[i]=1,pr--; for(i=1;i<=nn;i++) if(ans[i]) pc('R'); else pc('L'); pc('\n'); return; } void work(){ n=read(); nn=n<<1; int i; for(i=1;i<=nn;i++) a[i]=read(); if(check1()) printans(); else if(check2()) printans(); else puts("-1"); return; } int main(){ //freopen("palin2.in","r",stdin); //freopen("1.out","w",stdout); int T=read(); while(T--) work(); return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析