inverse.in
输出文件:
inverse.out
简单对比
5 4 1 5 3 4 2 5 1 4 2
5 2 2 1 样例解释 (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
N<=100000 M<=50000
首先用树状数组求一下原始的逆序对,每次删除一个数x的时候,ans-=x后面比x小的数+x前面比x大的数
当然这样算会有重复,因为有些数有可能已经删去了,因此可以用一个二维变量(i,a[i])记录已经删去的值,用树状数组+线段树维护一下即可。时间复杂度O(nlog^2n)
(其实可以用CDQ分治来写,,,不过还是树写起来爽
#include
using namespace std;
typedef long long LL;
const int MX = 1e5 + 5;
const int MXM = MX * 80;
int n, m, cnt;
int sum[MXM], ls[MXM], rs[MXM];
int a[MX], fa[MX];
LL f[MX];
struct Tree {
int n;
vector T;
void init(int _n) {
T.clear();
n = _n;
T.resize(n + 1);
}
void add(int x, LL v) {
for (int i = x; i <= n; i += i & -i) T[i] += v;
}
LL sum(int x) {
if (x > n) x = n;
LL ret = 0;
for (int i = x; i > 0; i -= i & -i) ret += T[i];
return ret;
}
} T;
void update(int p, int val, int l, int r, int prt, int &rt) {
rt = ++cnt;
ls[rt] = ls[prt]; rs[rt] = rs[prt];
sum[rt] = sum[prt] + 1;
if (l == r) return;
int m = (l + r) >> 1;
if (p <= m) update(p, val, l, m, ls[prt], ls[rt]);
else update(p, val, m + 1, r, rs[prt], rs[rt]);
}
int query(int L, int R, int l, int r, int rt) {
if (L <= l && R >= r) return sum[rt];
int m = (l + r) >> 1, ret = 0;
if (L <= m) ret += query(L, R, l, m, ls[rt]);
if (R > m) ret += query(L, R, m + 1, r, rs[rt]);
return ret;
}
struct BTree {
int n;
vector T;
void init(int _n) {
T.clear();
n = _n;
T.resize(n + 1);
}
void add(int x, int y, int v) {
for (int i = x; i <= n; i += i & -i) update(y, v, 1, n, T[i], T[i]);
}
int sum(int x, int l, int r) {
if (x > n) x = n;
int ret = 0;
for (int i = x; i > 0; i -= i & -i) ret += query(l, r, 1, n, T[i]);
return ret;
}
} bt;
int main() {
//freopen("in.txt", "r", stdin);
freopen("inverse.in", "r", stdin);
freopen("inverse.out", "w+", stdout);
scanf("%d%d", &n, &m);
T.init(n);
bt.init(n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), fa[a[i]] = i;
LL ans = 0;
for (int i = n; i > 0; i--) {
f[i] = T.sum(a[i]);
ans += f[i];
T.add(a[i], 1);
}
for (int i = 1, x; i <= m; i++) {
printf("%lld\n", ans);
scanf("%d", &x);
int index = fa[x];
ans -= 2 * f[index] + index - x;
ans += bt.sum(index, x, n);
ans += bt.sum(n, 1, x) - bt.sum(index, 1, x);
bt.add(index, x, 1);
}
return 0;
}