CSP 2021 游记 & 题解
题解
Pro1 : 廊桥分配
思路:
Pro2 : 括号序列
思路:
Pro3 : 回文
思路:左侧第一个进队的,序列中另一个它(位置为pl)一定最后一个从左侧出队,这样把整段序列分为A[1 - pl]和B[pl+1 - 2*n],那么,此序列成立,当且仅当每次A、B的头或末有相同的数字。
模拟:
5
4 1 2 4 5 3 1 2 3 5
先拆成左右A、B
A: 4 1 2 4
B: 5 3 2 1 3 5 (注意要反着拆)
接着,我们依次取出:
(4,4) (5,5) (3,3) (1,1) (2,2)
第一个数字是A序列的,就在前面加一个L,否则加一个R
第二个数字插在后面,其他同理
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<iomanip>
#include<cstring>
#include<string>
#define N 500010
using namespace std;
int T, n, a[N << 1], cl = 1, cr = 1;
bool L[N << 1], R[N << 1];
long long read(){
long long x=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')h=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*h;
}
int pd (int x, int y) {
if (x == -1 && y == -1)return -1;
if (x == -1) return 2;
return 1;
}
int main(){
T = read();
while (T --) {
cl = cr = 1; // 记得恢复状态!!!
n = read();
for (int i = 1; i <= n << 1; i ++) a[i] = read();
int pl = 0, pr = 0;
for (int i = 1; i <= (n << 1); i ++) {
if (a[i] == a[1] && i != 1) pl = i;
if (a[i] == a[n << 1] && i != n << 1) pr = i;
if(pl && pr) break;
}
/*
细节一:若给出序列首位相同,则pl=n*2,pr=1。不能写成这样:
for (int i = 2; i <= (n << 1) - 1; i ++) {
if (a[i] == a[1]) pl = i;
if (a[i] == a[n << 1]) pr = i;
if(pl && pr) break;
}
*/
// cout<<pl<<"==="<<pr<<endl;
// SOL1
for (int l1 = 1, r1 = pl, l2 = n << 1, r2 = pl + 1; l1 <= r1 || r2 <= l2; ) {
// 细节二:是||不是&&,因为A或B序列可能有一个已经删空了,但另一个还能删。
// 细节三:因为B序列是反过来的,所以l2=n*2,r2=pl+1。
if (a[l1] == a[r1] && l1 < r1) { // 细节四:判断顺序应遵从答案字典序最小的原则,故为(l1,r1)(l1,r2)(l2,r1)(l2,r2),这样可以保证字典序最小
L[cl] = 1; L[n * 2 - cl + 1] = 1;
l1 ++; r1 --;
}
else if (a[l1] == a[r2]) {
L[cl] = 1; L[n * 2 - cl + 1] = 0;
l1 ++; r2 ++;
}
else if (a[l2] == a[r1]) {
L[cl] = 0; L[n * 2 - cl + 1] = 1;
l2 --; r1 --;
}
else if (a[l2] == a[r2] && l2 > r2) {
L[cl] = 0; L[n * 2 - cl + 1] = 0;
l2 --; r2 ++;
}
else {
cl = -1; break; // 细节五:如果发现无法配对,立即退出
}
cl ++;
}
// cout<<cl<<endl;
// SOL2
// 细节六:在复制第二遍的时候,一定要注意该改的改了没,如'L'->'R';'pl'->'pr';'cl'->'cr'
for (int l1 = 1, r1 = pr, l2 = n << 1, r2 = pr + 1; l1 <= r1 || r2 <= l2; ) {
if (a[l1] == a[r1] && l1 < r1) {
R[cr] = 1; R[n * 2 - cr + 1] = 1;
l1 ++; r1 --;
}
else if (a[l1] == a[r2]) {
R[cr] = 1; R[n * 2 - cr + 1] = 0;
l1 ++; r2 ++;
}
else if (a[l2] == a[r1]) {
R[cr] = 0; R[n * 2 - cr + 1] = 1;
l2 --; r1 --;
}
else if (a[l2] == a[r2] && l2 > r2) {
R[cr] = 0; R[n * 2 - cr + 1] = 0;
l2 --; r2 ++;
}
else {
cr = -1; break;
}
cr ++;
}
// cout<<cr<<endl;
int tp = pd(cl, cr);
if (tp == 1) {
for (int i = 1; i <= 2 * n; i ++) {
putchar(L[i] == 1 ? 'L':'R');
}
putchar('\n');
}
else if (tp == 2) {
for (int i = 1; i <= 2 * n; i ++) {
putchar(R[i] == 1 ? 'L':'R');
}
putchar('\n');
}
else {
printf("-1\n");
}
}
return 0;
}
Pro4 : 交通规划
思路:

浙公网安备 33010602011771号