序列(sequence)
题目链接: 序列(sequence)
csdn食用更佳:序列(sequence)
时间限制:C/C++ 1000MS,其他语言 2000MS
内存限制:C/C++ 256MB,其他语言 512MB
描述
a, b 为两个长度为 n 的序列,定义它们的距离为
现在给你两个序列 a 和 b,你可以任意交换 a 中的两个元素。
请你求出经过若干次交换之后,两个序列的最小距离,对 998244353 取模。
并求出最少的交换步数。
保证 a, b 序列中没有相同的元素,即
输入描述
第一行两个数字 n, T,分别表示序列长度和任务类型,其中
第二行 n 个整数
第三行 n 个整数
输出描述
第一个数,输出两个序列的最小距离对 998244353 取模的结果。
如果
思路分析
-
距离计算:
定义两个序列 和 的距离为 。
我们需要通过交换 中的元素来最小化这个距离。 -
最小化距离:
由于 和 中的元素都是唯一的,我们可以通过将 中的元素重新排列,使得 尽可能接近 。
具体来说,我们可以将 和 中的元素按相同的顺序排序,这样 和 的对应关系就是最优的。 -
计算最小交换次数:
为了计算最少的交换次数,我们需要找到 中的元素与 中的元素之间的置换环。
每个置换环的长度减去 就是该环需要的交换次数。
总的交换次数就是所有置换环的交换次数之和。
具体步骤
-
读取输入:
- 读取
和 。 - 读取序列
和 。
- 读取
-
计算最小距离:
- 将
和 分别排序。 - 计算排序后的
和 的距离。
- 将
-
计算最小交换次数如果
:- 构建一个映射,将
中的每个元素映射到 中的对应位置。 - 使用深度优先搜索(DFS)或并查集来找到所有的置换环。
- 计算每个置换环的长度,并求出总的交换次数。
- 构建一个映射,将
代码实现
#include <bits/stdc++.h>
using namespace std;
const int N = 6e5 + 5;
const long long MOD = 998244353;
int n, t;
pair<int, int> a[N], b[N];
int p[N];
int main()
{
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
scanf("%d %d", &n, &t);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a[i].first);
a[i].second = i;
}
for (int i = 1; i <= n; ++i)
{
scanf("%d", &b[i].first);
b[i].second = i;
}
sort(a + 1, a + n + 1),sort(b + 1, b + n + 1);
long long ans = 0;
for (int i = 1; i <= n; ++i)
{
p[a[i].second] = b[i].second; // 将序列 A 中的元素对应到序列 B 中的位置
ans = (ans + (long long)(a[i].first - b[i].first) * (a[i].first - b[i].first)) % MOD;
}
long long sum = 0;
for (int i = 1; i <= n; ++i)
{
while (p[i] != i) // 如果当前位置的对应不是自己
{
swap(p[i], p[p[i]]); // 交换对应关系,使其正确
sum++;
}
}
printf("%lld ", ans);
if (t == 1)
{
printf("%lld\n", sum);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】