E2 - Permutation Minimization by Deque
每一个数不是放在开头就是放在结尾,直接用树状数组维护,数据很大,也需要离散化一下,相同的值注意不要离散成不同的值。
对于每一个数,用树状数组比较,是放在开头更优还是放在结尾更优。
int x1 = que(a[i].val - 1);-----------x1表示把当前的数放在开头会产生x1的逆序对。
int y1 = que(n) - que(a[i].val);--------y1表示把当前的数放在结尾会产生y1的逆序对。
ans+=两者中的最小值就好了。
不管数放在开头还是结尾,在c数组中都是放在定好的位置上,所以直接add(a[i],1)。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5, mod = 998244353;
struct node {
int val, pos;
bool operator < (const node &k) const {
if (val != k.val) return val < k.val;
else return pos < k.pos;
}
}a[N];
int c[N];
int b[N];
int n;
int lowbit(int x) { return x & -x; }
void add(int i, int x)
{
while (i <= n) {
c[i] += x;
i += lowbit(i);
}
}
int que(int i)
{
int ret = 0;
while(i > 0) {
ret += c[i];
i -= lowbit(i);
}
return ret;
}
/* priority_queue<node> q;
struct pp{
int x, y;
} ans[N]; */
signed main()
{
/* ios::sync_with_stdio(false);
cin.tie(0); */
int t;
cin >> t;
while(t--) {
cin >> n;
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i].val);
a[i].pos = i;
b[i] = a[i].val;
}
sort(b + 1, b + 1 + n);
for (int i = 1; i <= n; i++) a[i].val = lower_bound(b + 1, b + 1 + n, a[i].val) - b;
int ans = 0;
for (int i = 1; i <= n; i++) {
add(a[i].val, 1);
int x1 = que(a[i].val - 1);
int y1 = que(n) - que(a[i].val);
ans += min(x1, y1);
}
cout << ans << endl;
// memset(c, 0, sizeof(c));
for (int i = 1; i <= n; i++) c[i] = 0;
}
return 0;
}