CF1579E2 Array Optimization by Deque
CF1579E2
原题链接←Click it
题目大意:给定一个数组\(a\),依次将\(a\)中的每个元素放到一个双端队列中,求逆序对可能的最小值。
解题思路:首先对于\(a_1\),从前端插入和从尾端插入效果都是一样的。那么\(a_2\)无论是前端插入还是后端插入,都要考虑到\(a_1\),依次类推,对于任意\(a_i(i > 1)\),都必须考虑\(a_1,a_2,...,a_{i-1}\),那么就可以贪心地插入\(a_i\),如果在前端的逆序对数量少就插在前端,反之就差在尾端。因此就可以构建一颗平衡树,里面存放的是队列中已有元素的个数,每次可以用\(log\)的复杂度求出插入前端和插入尾端的逆序对个数。
参考代码:
struct BIT {
int N;
vector<int> c;
BIT (int n) : N(n) {
c.resize(n + 1, 0);
}
void add(int x, int d) {
for(;x <= N; x += x & -x) {
c[x] += d;
}
}
int sum(int x) {
int res = 0;
for(;x; x -= x & -x) {
res += c[x];
}
return res ;
}
int sum(int x, int y) {
return sum(y) - sum(x);
}
};
void solve() {
int n;
cin >> n;
vector<int> a(n);
for(int i = 0; i < n; i ++) {
cin >> a[i];
}
vector<int> b = a;
sort(b.begin(), b.end());
b.resize(unique(b.begin(), b.end()) - b.begin());
for(int i = 0; i < n; i ++) {
a[i] = lower_bound(b.begin(), b.end(), a[i]) - b.begin() + 1;
}
int cnt = b.size();
ll res = 0;
BIT bit(cnt);
for(int i = 0; i < n; i ++) {
res += min(bit.sum(a[i] - 1), bit.sum(a[i], cnt));
bit.add(a[i], 1);
}
cout << res << '\n';
}