Idea: Change deletion operation to add operation, and use the method of time reversal to deal with it. So imagine the number of reverse pairs that can be increased by inserting a number xxx into position iii for a sequence?
The contribution of the insertion point is calculated in two parts, one is that the larger number before position i can form an inverse pair, the other is that the smaller number after position i can form an inverse pair.
Therefore, the problem can be regarded as a three-dimensional partial ordering problem (adding time, adding location, adding value size).
So we can solve this problem perfectly by sorting one-dimensional time, dividing and conquering cdqcdq, and then dealing with one-dimensional tree array.
#include <bits/stdc++.h> #define eps 1e-8 #define INF 0x3f3f3f3f #define PI acos(-1) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define CLR(x, y) memset((x),y,sizeof(x)) #define fuck(x) cerr << #x << "=" << x << endl; using namespace std; typedef long long ll; typedef unsigned long long ull; const int seed = 131; const int maxn = 1e5 + 5; const int mod = 1e9 + 7; const int N = 1e5 + 5; int n, m; int a[maxn], b[maxn]; int bit[maxn]; int vis[maxn]; int pos[maxn]; int lowbit(int x) { return x & -x; } void add(int i, int x) { while (i < N) { bit[i] += x; i += lowbit(i); } } int query(int i) { int sum = 0; while (i) { sum += bit[i]; i -= lowbit(i); } return sum; } struct node { int t, p, val; ll ans; bool operator<(const node &a) const { return t < a.t; } } e[maxn], t[maxn]; ll ans[maxn]; void cdq(int l, int r) { if (l == r) return; int mid = (l + r) / 2; cdq(l, mid); cdq(mid + 1, r); int i = l, j = mid + 1; int cnt = l; while (i <= mid || j <= r) { if ((j > r) || (i <= mid && e[i].p < e[j].p)) { add(e[i].val, 1); t[cnt++] = e[i++]; } else { ll sum = (i - l) - query(e[j].val); e[j].ans += sum; t[cnt++] = e[j++]; } } for (int i = l; i <= mid; i++) { add(e[i].val, -1); } for (int i = l; i <= r; i++) { e[i] = t[i]; } } void cdq2(int l, int r) { if (l == r) return; int mid = (l + r) / 2; cdq2(l, mid); cdq2(mid + 1, r); int i = l, j = mid + 1; int cnt = l; while (i <= mid || j <= r) { if ((j > r) || (i <= mid && e[i].p > e[j].p)) { add(e[i].val, 1); t[cnt++] = e[i++]; } else { ll sum = query(e[j].val); e[j].ans += sum; t[cnt++] = e[j++]; } } for (int i = l; i <= mid; i++) { add(e[i].val, -1); } for (int i = l; i <= r; i++) { e[i] = t[i]; } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); pos[a[i]] = i; } for (int i = 1; i <= m; i++) { scanf("%d", &b[i]); vis[b[i]] = 1; } int tmp = m; for (int i = 1; i <= n; i++) { if (!vis[i]) b[++tmp] = i; } for (int i = n; i >= 1; i--) { e[i].t = n - i + 1; e[i].p = pos[b[i]]; e[i].val = b[i]; } sort(e + 1, e + 1 + n); cdq(1, n); CLR(bit, 0); CLR(t, 0); sort(e + 1, e + 1 + n); cdq2(1, n); sort(e + 1, e + 1 + n); for (int i = 1; i <= n; i++) { ans[i] = ans[i - 1] + e[i].ans; } for (int i = n; i > n - m; i--) printf("%lld\n", ans[i]); return 0; }