[题目链接]
[算法]
首先将式子化简 :
sigma( (ai - bi) ^ 2) = sigma( ai^2 + bi^2 - 2aibi )
显然 , 只需最大化aibi就能最小化“距离”
考虑贪心 , 将a中最小元素与b中最小元素组合 , a中第二小与b中第二小组合 ... , 不难证明这样是最优的 ,
因为 : 设a < b , c < d , 将a与c组合 , b与d组合比a与d组合 , b与c组合更优。
不妨先将a和b升序排序 ,记录每个元素的初始位置 , 构造新序列p, 令p[a[i].id] = b[i].id , 问题就转化为了 , 每次可以交换相邻两个元素 , 要求用最少的次数时p按升序排列。
只需求出逆序对数即可。 可以用归并排序或树状数组实现 , 笔者使用的是树状数组
时间复杂度 :O(NlogN)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 const int P = 99999997; struct info { int value; int id; } a[MAXN],b[MAXN]; int n,ans; int c[MAXN]; template <typename T> inline void read(T &x) { int f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } struct Binary_Indexed_Tree { int c[MAXN]; inline int lowbit(int x) { return x & (-x); } inline void modify(int pos,int val) { for (int i = pos; i <= n; i += lowbit(i)) c[i] = (c[i] + val) % P; } inline int query(int pos) { int ret = 0; for (int i = pos; i; i -= lowbit(i)) ret = (ret + c[i]) % P; return ret; } } BIT; inline bool cmp(info a,info b) { return a.value < b.value; } int main() { read(n); for (int i = 1; i <= n; i++) { read(a[i].value); a[i].id = i; } for (int i = 1; i <= n; i++) { read(b[i].value); b[i].id = i; } sort(a + 1,a + n + 1,cmp); sort(b + 1,b + n + 1,cmp); for (int i = 1; i <= n; i++) c[a[i].id] = b[i].id; for (int i = 1; i <= n; i++) { ans = (ans + (i - BIT.query(c[i] - 1) - 1) % P + P) % P; BIT.modify(c[i],1); } printf("%d ",ans); return 0; }