火柴排队
问题 B: 火柴排队
时间限制: 1 Sec 内存限制: 128 MB提交: 11 解决: 7
[提交] [状态] [讨论版] [命题人:admin]
题目描述
涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:,其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最 小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最 小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
输入
输入共三行,第一行包含一个整数 n,表示每盒中火柴的数目。
第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint
输出
输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。
样例输入
4
2 3 1 4
3 2 1 4
样例输出
1
提示
最小距离是 0,最少需要交换 1 次,比如:交换第 1 列的前 2 根火柴或者交换第 2 列的前 2 根火柴。
Solution:最小距离即为从小到大排序后的结果(高中数学竞赛的基本常识),然后保持B不动,移动A,这样就转换成求逆序对数的问题了。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include<bits/stdc++.h> #define REP(i, a, b) for(int i = (a); i <= (b); ++ i) #define REP(j, a, b) for(int j = (a); j <= (b); ++ j) #define PER(i, a, b) for(int i = (a); i >= (b); -- i) using namespace std; typedef long long ll; const int mod=99999997; const int maxn=1e5+5; template <class T> inline void rd(T &ret){ char c; ret = 0; while ((c = getchar()) < '0' || c > '9'); while (c >= '0' && c <= '9'){ ret = ret * 10 + (c - '0'), c = getchar(); } } struct node{ ll w,id; bool operator<(const node& x)const{ return w<x.w; } }p[maxn],q[maxn]; ll n,r[maxn],ans,tot[maxn]; void update(int cur){ while(cur<=n)tot[cur]++,cur+=(cur&(-cur)); } int sum(int cur){ int ans=0; while(cur)ans+=tot[cur],cur-=(cur&(-cur)); return ans; } int main(){ rd(n); REP(i,1,n)rd(p[i].w),p[i].id=i; REP(i,1,n)rd(q[i].w),q[i].id=i; sort(p+1,p+1+n); sort(q+1,q+1+n); REP(i,1,n)r[p[i].id]=q[i].id; REP(i,1,n){ update(r[i]),ans+=i-sum(r[i])%mod; } cout<<ans%mod<<endl; }