[Leaf] [CF2162E] Beautiful Palindromes

cf2162e---beautiful-palindromes">CF2162E - Beautiful Palindromes

1. 题面梗概

中译中: 给定一个长度为 nn 的数组 aa,你需要向其末尾追加 kk 个范围在 [1,n][1,n] 的数。目标是使得最终数组中的回文子数组的数量最少。

2. 逻辑推导

从回文串的性质入手:

  • 长度为 11 :x | 长度为 22 :xx | 长度为 33 :xxx, xyx | 长度为 44 :xxxx,xyyx

所以我们只需要构造任意连续三个数都不同,那么就不会产生任意一个长度 >1> 1 的回文。

题目限定 n≥3n \geq 3,我们一定能找到三个互不相同的数 x,y,z{x,y,z} 形成循环。

  • Case 1: aa 是排列。直接取末尾三个数即可 an,an−1,an−2{a_n,a_{n-1},a_{n-2}}。
  • Case 2:aa 不是排列。那就意味着有一个数从未出现过,令其为 xx,同时令 z=anz = a_n,那么我们只需要再找出一个 y≠x,zy \neq x,z 即可。

3. 代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using PII = pair<int, int>;

const int maxn = 2e5 + 5;
int cnt[maxn];
int a[maxn];
int n, k;

void solve( )
{
cin >> n >> k;

for( int i = 1; i <= n; ++ i )
{
cnt[i] = 0;
}

for( int i = 1; i <= n; ++ i )
{
cin >> a[i];
cnt[a[i]] ++;
}

int x = -1;
for( int i = 1; i <= n; ++ i )
{
if( cnt[i] != 0 ) continue;
x = i;
break;
}

vector< int > res;

if( x == -1 )
{
// Case 1 排列
int tmp[3] = {a[n - 2], a[n - 1], a[n]};
for( int i = 0; i < k; ++ i )
{
res.push_back( tmp[i % 3] );
}
}
else
{
// Case 2 非排列
int z = a[n];
int y = -1;

for( int i = 1; i <= n; ++ i )
{
if( i == x || i == z ) continue;
y = i;
break;
}

int tmp[3] = {x, y, z};
for( int i = 0; i < k; ++ i )
{
res.push_back( tmp[i % 3] );
}
}

for( int x : res )
{
cout << x << " ";
}
cout << '\n';
}

int main( )
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int _t = 1;
cin >> _t;
while( _t -- )
{
solve( );
}
return 0;
}

4. 复盘

  • 复杂度: O(N+K)O( N + K )
  • 碎碎念: 构造题~怎么又是构造题?本题考察了回文串的构造,不算很难,想到了就会写,题目给的 n≥3n \geq 3 也很诱人。
  • 关联笔记: 构造策略

[Leaf] [CF2162E] Beautiful Palindromes
http://miqiu.space/posts/d212ef75/
作者
Miqiu
发布于
2026年1月19日
许可协议