ARC 155(Even Sum Triplet)题解
构造题,思路简单,但很多细节(多的逆天, W A \mathcal{WA} WA 了一万遍,忘了我吧)
简单题意:你可以做任意次如下操作。
选择一个 i i i,满足 1 ≤ i ≤ n − 2 1 \leq i \leq n - 2 1≤i≤n−2, 且 a [ i ] + a [ i + 1 ] + a [ i + 2 ] a[i] + a[i + 1] + a[i + 2] a[i]+a[i+1]+a[i+2] 是一个偶数,将 a [ i ] , a [ i + 1 ] , a [ i + 2 ] a[i],a[i + 1], a[i + 2] a[i],a[i+1],a[i+2] 随意排序,回答 A A A 序列能否通过任意次操作变为 B B B。
三个数加起来为偶数,只有可能是
1.偶数+偶数+偶数
2.偶数+奇数+奇数
结论一:
相邻三个数有两个奇数一个偶数(简称为可以组成一组)的话,两个奇数可以一起移动向左移动一位或者向右移动一位,并且除去他们两个后的奇数组成的序列不变。
证明:
容易构造出来一种方案,无非分为两种情况。
只考虑向左移动,向右同理。
令 a [ i ] a[i] a[i] 为偶数, a [ i + 1 ] , a [ i + 2 ] a[i + 1],a[i + 2] a[i+1],a[i+2]为奇数
1. 奇数,
a
[
i
]
,
a
[
i
+
1
]
,
a
[
i
+
2
]
a[i], a[i + 1], a[i + 2]
a[i],a[i+1],a[i+2]
a
[
i
−
1
]
,
a
[
i
]
,
a
[
i
+
1
]
,
a
[
i
+
2
]
→
a
[
i
+
1
]
,
a
[
i
]
,
a
[
i
−
1
]
,
a
[
i
+
2
]
→
a
[
i
+
1
]
,
a
[
i
+
2
]
,
a
[
i
]
,
a
[
i
−
1
]
→
a
[
i
]
,
a
[
i
+
1
]
,
a
[
i
+
2
]
,
a
[
i
−
1
]
a[i - 1], a[i], a[i + 1], a[i + 2] \\ \rightarrow a[i + 1],a[i],a[i - 1],a[i + 2] \\ \rightarrow a[i + 1],a[i + 2],a[i], a[i - 1] \\ \rightarrow a[i],a[i + 1], a[i + 2], a[i - 1]
a[i−1],a[i],a[i+1],a[i+2]→a[i+1],a[i],a[i−1],a[i+2]→a[i+1],a[i+2],a[i],a[i−1]→a[i],a[i+1],a[i+2],a[i−1]
a [ i ] , a [ i + 1 ] , a [ i + 2 ] a[i],a[i + 1],a[i + 2] a[i],a[i+1],a[i+2] 为新的一组
2. 偶数,
a
[
i
]
,
a
[
i
+
1
]
,
a
[
i
+
2
]
a[i],a[i + 1],a[i + 2]
a[i],a[i+1],a[i+2]
a
[
i
−
1
]
,
a
[
i
]
,
a
[
i
+
1
]
,
a
[
i
+
2
]
→
a
[
i
−
1
]
,
a
[
i
+
1
]
,
a
[
i
+
2
]
,
a
[
i
]
a[i - 1], a[i], a[i + 1], a[i + 2] \\ \rightarrow a[i - 1], a[i + 1], a[i + 2], a[i]
a[i−1],a[i],a[i+1],a[i+2]→a[i−1],a[i+1],a[i+2],a[i]
a [ i − 1 ] , a [ i + 1 ] , a [ i + 2 ] a[i - 1],a[i + 1],a[i + 2] a[i−1],a[i+1],a[i+2] 为新的一组
Ex·结论一
存在三个数可以组成一组的话,奇数间相对顺序可以任意排列,并且偶数间相对顺序不变。
证明:
由于相邻两项可以随意交换等价于任意排列这个序列(冒泡排序),我们只需证明相邻两个奇数的相对顺序可以随意交换即可。
设想交换的两个奇数为 i , j i,j i,j, k , k + 1 , k + 2 k,k +1,k + 2 k,k+1,k+2 为一组。
构造一种交换方案。
那么我们可以将 k , k + 1 , k + 2 k, k + 1, k + 2 k,k+1,k+2 移到 j j j 的右边,然后 j , k , k + 1 j, k, k + 1 j,k,k+1 组为一组再将 j , k , k + 1 j,k,k + 1 j,k,k+1 移到 i i i 的左边,让 i , k , k + 1 i,k,k + 1 i,k,k+1 组为一组,再让 i , k , k + 1 i,k,k+1 i,k,k+1 移到 k + 2 k + 2 k+2 的右边,让 k , k + 1 , k + 2 k, k + 1, k + 2 k,k+1,k+2 组为一组,这样就实现了 i , j i,j i,j 的相对位置改变。
由于一组的平移使除了这组的奇数组成的序列不变,所以只有 i , j i, j i,j 相对位置发生了改变。
结论二:
偶数+奇数+奇数这种类型任意变换都无法改变偶数间的相对顺序。
所以偶数相对位置改变只能靠三个偶数的这种情况。
结论三:
A A A 序列存在组,则 A A A 变化后,序列也存在组。
i , j , k i, j, k i,j,k 重排列,说明 i , j , k i, j, k i,j,k 是一个组,组内部顺序可以随便排列,所以 i , j , k i, j, k i,j,k 重排列后还是一个组。
综上结论
那么我们就能写出一个伪代码
if 偶数个数 >= 3 //偶数之间顺序可以随便(存在一组的情况下)
if a 有组
if b 有组 :yes
else :no
else
if b 有组 :no
else {
if 奇数位置不对应 :no
if 相邻奇数距离 >= 3 判断其间偶数随意排序能否相同,不对应 :no
else 判断其间偶数位置是否对应,不对应 :no
}
else if 2 >= 偶数个数 >= 1
判断偶数相对顺序是否对应,不对应 :no
if 奇数个数 >= 3 :yes//一定存在一个组
else if n == 4 暴力判断
else if n == 3 暴力判断
else//只有奇数
判断是否a,b是否一一对应
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define db double
#define LL long long
// #define int long long
#define PII pair <int, int>
#define ULL unsigned long long
#define MP(x,y) make_pair (x, y)
#define rep(i,j,k) for (int i = (j); i <= (k); i++)
#define per(i,j,k) for (int i = (j); i >= (k); i--)
template <typename T>
void read (T &x) {
x = 0; T f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar ();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar ();
}
x *= f;
}
template <typename T, typename... Args>
void read (T &x, Args&... Arg) {
read (x), read (Arg...);
}
const int MaxPrint = 1000;
int Poi_For_Print, Tmp_For_Print[MaxPrint + 5];
template <typename T>
void write (T x) {
if (x == 0) {
putchar ('0');
return;
}
bool flag = (x < 0 ? 1 : 0);
x = (x < 0 ? -x : x);
while (x) Tmp_For_Print[++Poi_For_Print] = x % 10, x /= 10;
if (flag) putchar ('-');
while (Poi_For_Print) putchar (Tmp_For_Print[Poi_For_Print--] + '0');
}
template <typename T, typename... Args>
void write (T x, Args... Arg) {
write (x); putchar (' '); write (Arg...);
}
template <typename T, typename... Args>
void print (T x, char ch) {
write (x); putchar (ch);
}
template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }
const int Maxn = 2 * 1e5;
int n, cnt1, cnt2;
int a[Maxn + 5], b[Maxn + 5];
int c[Maxn + 5], d[Maxn + 5];
int fk1, st1[Maxn + 5], fk2, st2[Maxn + 5];
signed main () {
// freopen ("C:\\Users\\BZ\\Desktop\\.vscode\\1.in", "r", stdin);
// freopen ("C:\\Users\\BZ\\Desktop\\.vscode\\1.out", "w", stdout);
read (n);
rep (i, 1, n)
read (a[i]), c[i] = a[i];
rep (i, 1, n)
read (b[i]), d[i] = b[i];
sort (c + 1, c + 1 + n);
sort (d + 1, d + 1 + n);
rep (i, 1, n)
if (c[i] != d[i]) {
printf ("No");
return 0;
}
rep (i, 1, n) {
if (a[i] & 1) cnt1++;
else cnt2++;
}
if (cnt2 >= 3) {
rep (i, 1, n - 1) {
if (((a[i] & 1) && (a[i + 1] & 1)) || (i + 2 <= n && (a[i] & 1) && (a[i + 2] & 1))) {
bool fl = 0;
rep (j, 1, n - 1) {
if (((b[j] & 1) && (b[j + 1] & 1)) || (j + 2 <= n && (b[j] & 1) && (b[j + 2] & 1))) {
fl = 1;
break;
}
}
if (fl == 1) printf ("Yes");
else printf ("No");
return 0;
}
}
//sort (a + 1, a + 1 + n)
int lst = 1;
rep (i, 1, n) {
if (a[i] & 1) {
if (a[i] != b[i]) {
printf ("No");
return 0;
}
if (i - lst >= 3) {
sort (a + lst, a + 1 + i - 1);
sort (b + lst, b + 1 + i - 1);
rep (j, lst, i - 1) {
if (a[j] != b[j]) {
printf ("No");
return 0;
}
}
}
else {
rep (j, lst, i - 1) {
if (a[j] != b[j]) {
printf ("No");
return 0;
}
}
}
lst = i + 1;
}
}
printf ("Yes");
}
else if (cnt2) {
rep (i, 1, n) {
if (!(a[i] & 1))
st1[++fk1] = a[i];
if (!(b[i] & 1))
st2[++fk2] = b[i];
}
rep (i, 1, fk1)
if (st1[i] != st2[i]) {
printf ("No");
return 0;
}
if (cnt1 >= 3) {
printf ("Yes");
}
else {
if (n == 4) {//2 + 2
bool fl1 = 0, fl2 = 0;
if ((a[1] & 1) && (a[4] & 1)) fl1 = 1;
if ((b[1] & 1) && (b[4] & 1)) fl2 = 1;
if (fl1 ^ fl2) {
if (fl1) {
rep (i, 1, n)
if (a[i] != b[i]) {
printf ("No");
return 0;
}
printf ("Yes");
}
else {
printf ("Yes");
}
}
else printf ("No");
}
else {//1 + 2
if (cnt1 == 2) printf ("Yes");
else {
rep (i, 1, n)
if (a[i] != b[i]) {
printf ("No");
return 0;
}
printf ("Yes");
}
}
}
}
else {
rep (i, 1, n)
if (a[i] != b[i]) {
printf ("No");
return 0;
}
printf ("Yes");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现