当a列火柴和对应的每一个b列火柴差值最小时,答案最小
也就是说,需要a列的第i高火柴与b列的第i高火柴在位置上相对应
但是这个操作比较难想,我们不妨设f(x)为a列第x高火柴的位置在b列中的位置(注意,x指a列第x高火柴在a列的位置,而f(x)是位置与位置的映射)。这十分相似于求最长公共子序列的nlogn做法
而目标转化为使f[x] = x,也就是说把f(x)转换为一个递增序列,那么转换的操作次数就是f(x)的逆序对数,并且,对f(x)的操作即对b列的操作
//归并排序
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 100000 + 10;
const int MOD = 99999997;
int f[MAXN],t[MAXN],cnt,n;
struct Node{
int num, ord;
}a[MAXN], b[MAXN];
bool cmp(Node a, Node b) {
return a.num < b.num;
}
void mergesort(int l, int r) {
if(l == r) return;
int mid = l+r>>1;
mergesort(l,mid);
mergesort(mid+1,r);
int size = 0, tl = l, tr = mid+1;
while(tl <= mid || tr <= r) {
if(tr > r || tl<=mid && f[tl] < f[tr]) {
t[++size] = f[tl++];
} else {
t[++size] = f[tr++];
cnt = (cnt%MOD + mid - tl + 1) % MOD;
}
}
for(int i=l; i<=r; i++) {
f[i] = t[i-l+1];
}
}
int main() {
cin >> n;
for(int i=1; i<=n; i++) {
cin >> a[i].num;
a[i].ord = i;
}
for(int i=1; i<=n; i++) {
cin >> b[i].num;
b[i].ord = i;
}
sort(a+1,a+n+1,cmp);
sort(b+1,b+n+1,cmp);
for(int i=1; i<=n; i++) {
f[a[i].ord] = b[i].ord;
}
mergesort(1,n);
cout << cnt % MOD;
return 0;
}
//树状数组
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 100000 + 10;
const int MOD = 99999997;
int f[MAXN],t[MAXN],cnt,n,tree[MAXN];
struct Node{
int num, ord;
}a[MAXN], b[MAXN];
bool cmp(Node a, Node b) {
return a.num < b.num;
}
int lowbit(int x) {
return x&(-x);
}
void update(int pos, int value) {
while(pos <= n) {
tree[pos] = (tree[pos] + value % MOD) % MOD;
pos += lowbit(pos);
}
}
int getsum(int pos) {
int sum = 0;
while(pos) {
sum = (sum % MOD + tree[pos]) % MOD;
pos -= lowbit(pos);
}
return sum;
}
int inverse(int pos) {
return (pos - getsum(f[pos])) % MOD; // pos是位置,getsum求的是目前序列中比f[pos]小的数,做差就是逆序对数
}
int main() {
cin >> n;
for(int i=1; i<=n; i++) {
cin >> a[i].num;
a[i].ord = i;
}
for(int i=1; i<=n; i++) {
cin >> b[i].num;
b[i].ord = i;
}
sort(a+1,a+n+1,cmp);
sort(b+1,b+n+1,cmp);
for(int i=1; i<=n; i++) {
f[a[i].ord] = b[i].ord;
}
for(int i=1; i<=n; i++) {
update(f[i], 1);
cnt = (cnt % MOD + inverse(i)) % MOD;
}
cout << cnt % MOD;
return 0;
}