构造题练习CF2052A. Adrenaline Rush
构造题练习
思路
-
遇到一个逆序对要完成一次超车,遇到一个正序对可以看成先超车然后又被超回来了,所以完成了两次超车,最多的超车次数很好求
-
比较难的是按顺序求出超车的序列
-
一个想法是按照最终的序列从最后一辆车开始往前处理,找到它在最初序列中的位置一直向前超车,到达第一个,然后被别的车超到达它应该在的位置
- 为什么要从最后一个开始处理呢?这样处理其他车的时候就不用考虑它的影响了
- 过程中需要记录每一个车的实时位置,和每一个位置是哪一辆车
- 举个例子
- 给定序列 1 2 4 3,根据题意每辆车的初始位置1 2 3 4
- 从最后一个开始处理,最后一个位置是车3,它初始位置是位置3
- 那么从位置3往前面超,一直到第一个 3 1 2 4,然后被后面的车超到应在的位置 1 2 4 3
- ......
代码
#pragma optimize GCC(2)
#pragma optimize GCC(3)
#pragma optimize GCC("Ofast")
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define lowbit(x) x & -x
using i64 = long long;
using u64 = unsigned long long;
using ld = long double;
const int maxn = 2e5 + 5;
const int inf = 0x7f7f7f7f;
const int mod = 1e9 + 7;
void solve()
{
int n = 0;
std::cin >> n;
std::vector<int> nums(n + 1, 0);
std::vector<int> pos(n + 1, 0), mp(n + 1, 0);
// pos[i], i这个数在哪一个位置
// mp[i], i这个位置是哪一个数
for (int i = 1; i <= n; i++)
{
std::cin >> nums[i];
pos[i] = i;
mp[i] = i;
}
std::vector<std::pair<int, int>> res;
for (int to = n; to >= 1; to--)
{
int t = nums[to];
int p = pos[t];
for (int i = p - 1; i >= 1; i--)
{
res.push_back({t, mp[i]});
pos[t] = i;
pos[mp[i]] = i + 1;
mp[i + 1] = mp[i];
mp[i] = t;
}
for (int i = 2; i <= to; i++)
{
res.push_back({mp[i], t});
pos[t] = i;
pos[mp[i]] = i - 1;
mp[i - 1] = mp[i];
mp[i] = t;
}
}
std::cout << res.size() << endl;
for (auto [x, y] : res)
{
std::cout << x << " " << y << endl;
}
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr); std::cout.tie(nullptr);
//freopen("out.txt", "w", stdout);
int t = 1;
// std::cin >> t;
while(t--)
{
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现