题目大意:
分析:
对于每个数而言我存3个关键字
第一个是在初始序列中的位置
x
i
x_i
xi
第二个是这个数的值
y
i
y_i
yi
第三个是这个数在第几次操作时被删除,即
z
i
z_i
zi,当这个数没被操作删除时,
z
i
=
m
+
1
z_i=m+1
zi=m+1
那么我们考虑离线做,
求出初始序列的逆序对数,为
s
u
m
sum
sum
对于第
i
i
i次操作而言,假如删掉的是
x
x
x,
x
x
x在初始序列中的位置是
p
o
s
pos
pos,
那么删掉这个数给
s
u
m
sum
sum带来的代价就是
所有满足
x
i
<
p
o
s
,
y
i
>
x
,
z
i
>
i
x_i<pos,y_i>x,z_i>i
xi<pos,yi>x,zi>i的个数+所有满足
x
i
>
p
o
s
,
y
i
<
x
,
z
i
>
i
x_i>pos,y_i<x,z_i>i
xi>pos,yi<x,zi>i的个数
那么这个就是三维偏序辣
二遍 cdq分治套树状数组就没了
代码:
#include <iostream>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define mt(x) memset(x, 0, sizeof(x))
#define N 200005
using namespace std;
typedef long long ll;
struct Node {
int x, y, mark;
}C[N], tmp[N];
int orz[N], zyf[N], n, m, cdp, tot;
ll ans[N], sum;
void Ins(int x, int y) {
for (; x <= m + 1; x += (x & (-x))) zyf[x] += y;
}
int Cal(int x) {
int rp = 0;
for (; x; x -= (x & (-x))) rp += zyf[x];
return rp;
}
void cdq(int L, int R) {
if (R - L <= 1) return;
int mid = (L + R) >> 1;
cdq(L, mid);
cdq(mid, R);
int p = L, q = mid, cnt = 0;
while (p < mid && q < R) {
if (C[p].y > C[q].y) {
Ins(C[p].mark, 1); tmp[++cnt] = C[p++];
} else {
sum = sum + 1ll * (p - L);
if (C[q].mark <= m) ans[C[q].mark] = ans[C[q].mark] + 1ll * (Cal(m + 1) - Cal(C[q].mark));
tmp[++cnt] = C[q++];
}
}
while (q < R) {
sum = sum + 1ll * (p - L);
if (C[q].mark <= m) ans[C[q].mark] = ans[C[q].mark] + 1ll * (Cal(m + 1) - Cal(C[q].mark));
tmp[++cnt] = C[q++];
}
rep(i, L, p - 1) Ins(C[i].mark, -1);
while (p < mid) tmp[++cnt] = C[p++];
rep(i, 1, cnt) C[L + i - 1] = tmp[i];
}
bool cmp(Node aa, Node bb) {
return aa.x > bb.x;
}
void cdq1(int L, int R) {
if (R - L <= 1) return;
int mid = (L + R) >> 1;
cdq1(L, mid);
cdq1(mid, R);
int p = L, q = mid, cnt = 0;
while (p < mid && q < R) {
if (C[p].y < C[q].y) {
Ins(C[p].mark, 1); tmp[++cnt] = C[p++];
} else {
if (C[q].mark <= m) ans[C[q].mark] = ans[C[q].mark] + 1ll * (Cal(m + 1) - Cal(C[q].mark));
tmp[++cnt] = C[q++];
}
}
while (q < R) {
if (C[q].mark <= m) ans[C[q].mark] = ans[C[q].mark] + 1ll * (Cal(m + 1) - Cal(C[q].mark));
tmp[++cnt] = C[q++];
}
rep(i, L, p - 1) Ins(C[i].mark, -1);
while (p < mid) tmp[++cnt] = C[p++];
rep(i, 1, cnt) C[L + i - 1] = tmp[i];
}
int main() {
scanf("%d %d", &n, &m);
rep(i, 1, n) C[i].x = i, scanf("%d", &C[i].y);
int x;
rep(i, 1, m) scanf("%d", &x), orz[x] = i;
rep(i, 1, n)
if (orz[C[i].y]) C[i].mark = orz[C[i].y]; else C[i].mark = m + 1;
cdq(1, n + 1);
sort(C + 1, C + n + 1, cmp);
cdq1(1, n + 1);
rep(i, 1, m) {
printf("%lld\n", sum);
sum = sum - ans[i];
}
return 0;
}