[ARC181D] Prefix Bubble Sort 题解
朴素的方法当然就是直接模拟,复杂度貌似是 \(O(n^2 \log n)\),倒闭。
尝试优化无果。
我们不妨换个角度考虑:我们进行一轮 prefix 冒泡排序后,少了哪些逆序对?
进行冒泡排序时,我们相当于移动了 prefix max,剩下的元素集体向前 slide 一格,并与前面的 prefix max 拆散原有的逆序对,即产生 \(-1\) 的贡献。
注意到操作序列有序。
我们枚举所有元素 \(i\),查看前面大于自身的元素个数 \(s\),再 lower_bound 出第一次影响到 \(i\) 的操作编号 \(p\),那么这个非 prefix max 元素就会在操作 \([p, p+s-1]\) 均产生 \(-1\) 的贡献。差分算一下即可。
要算逆序对等等的,树状数组搞一下。
总时间复杂度 \(O(n \log n)\)。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Linf 0x3f3f3f3f3f3f3f3f
#define pii pair<int, int>
#define all(v) v.begin(), v.end()
using namespace std;
//#define filename "xxx"
#define FileOperations() freopen(filename".in", "r", stdin), freopen(filename".out", "w", stdout)
//#define multi_cases 1
namespace Traveller {
const int N = 2e5+2;
int n, a[N];
int m, b[N];
int lowbit(int x) { return x & -x; }
struct BIT {
int n, c[N];
void init(int n = 0) {
this->n = n;
memset(c, 0, sizeof(int) * (n+1));
}
void add(int idx, int v) { for(; idx <= n; idx += lowbit(idx)) c[idx] += v; }
int query(int idx) {
int res = 0;
for(; idx; idx -= lowbit(idx)) res += c[idx];
return res;
}
int query(int l, int r) { return query(r) - query(l-1); }
} tr;
int diff[N << 1];
void main() {
cin >> n;
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
cin >> m;
for(int i = 1; i <= m; ++i) scanf("%d", &b[i]);
long long ans = 0;
tr.init(n);
for(int i = 1; i <= n; ++i) {
ans += tr.query(a[i], n);
tr.add(a[i], 1);
}
tr.init(n);
for(int i = 1; i <= n; ++i) {
int p = lower_bound(b+1, b+m+1, i) - b;
int s = tr.query(a[i], n);
++diff[p], --diff[p + s];
tr.add(a[i], 1);
}
for(int i = 1; i <= m; ++i) diff[i] += diff[i-1];
for(int i = 1; i <= m; ++i) {
ans -= diff[i];
printf("%lld\n", ans);
}
}
}
signed main() {
#ifdef filename
FileOperations();
#endif
signed _ = 1;
#ifdef multi_cases
scanf("%d", &_);
#endif
while(_--) Traveller::main();
return 0;
}

浙公网安备 33010602011771号