P1966
[NOIP2013 提高组] 火柴排队
题目描述
涵涵有两盒火柴,每盒装有
其中
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对
对于
分析
依题意模拟即可
注意到,可以随意对两个数组进行排序。
分析可知若需要
如果考虑对两个数组都进行若干次交换,情况太复杂了。
发现这完全可以转化为只对其中一个数组的交换(比如说
又注意到,这两个数组的对应位置是相对独立的,那么有以下做法:
- 对
进行若干次交换,使得 作为第 大的数与 同样也是第 大的数相对应。 - (第
大指相对于各自的数组)
但是
假设
答案就是
如何进行转化呢? 需要重新指定数字间的大小关系。
关系是什么呢? 从
如果认为
不要忘了进行离散化!(把值域缩到
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const int mod = (114514+114514)*(-11+451-4)+114514+114*51*4+114*51+4+1/1-4+51*4;
int n, ans;
int a[N], b[N], to[N];
struct bitree{
int c[N], res;
inline int lb(int x) { return x & (-x); }
inline void add(int x, int v){
for (; x <= n; x += lb(x))
c[x] += v;
}
inline int find(int x){
for (res = 0; x; x -= lb(x))
res += c[x];
return res;
}
inline int find(int x, int y){
return find(y) - find(x - 1);
}
}tr;
map<int, int> mpa, mpb;
signed main(){
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i], mpa[a[i]] = i;
for (int i = 1; i <= n; i++)
cin >> b[i], mpb[b[i]] = i;
sort(a + 1, a + 1 + n); sort(b + 1, b + 1 + n);
for (int i = 1; i <= n; i++)
to[mpa[a[i]]] = mpb[b[i]];
for (int i = 1; i <= n; i++){
ans = (ans + tr.find(n - to[i])) % mod;
tr.add(n - to[i] + 1, 1);
}
cout << ans;
return 0;
}
Written with StackEdit中文版.
好玩,爱玩!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现