D - 动态逆序对 HYSBZ - 3295
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删
除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数
\(N<=100000 M<=50000\)
Sample Input
5
4 1 5 3 4
2
5
1
4
2
扫描二维码关注公众号,回复:
5607190 查看本文章
Sample Output
5
2
2
1
样例解释 (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
题解
正序删除就等以倒叙插入
在每个点上记录位置比他前的点和他产生的逆序对数量
对于一个新插入的节点\(A\):
- 如果一个以存在的点\(B\), $A.pos<B.pos ~&&~A.val>B.val \(,那么\)A\(对\)B$产生贡献
- 如果\(A.pos > B.pos~\&\&~A.val < B.val\), 那么\(B\)对\(A\)产生贡献
所以把\((Time, pos, val)\)做三维偏序, 注意左边和右边有双向的贡献
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 10;
inline LL in()
{
LL x = 0, flag = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') flag = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
return x * flag;
}
int n, m;
struct Fenwick
{
int val[MAXN];
void upd(int x, int v)
{
for (int i = x; i <= 100000; i += (i & (-i))) val[i] += v;
}
int qry(int x)
{
int ret = 0;
for (int i = x; i > 0; i &= (i - 1)) ret += val[i];
return ret;
}
} T, T2;
LL ans, an[MAXN];
int pos[MAXN], ask[MAXN];
struct Node
{
int t, p, v, id;
bool operator < (const Node & b) const
{
return t < b.t;
}
} a[MAXN], b[MAXN];
int mark[MAXN];
void merge(int l, int mid, int r)
{
int i = l, j = mid + 1, k = l;
while (k <= r)
{
if (j > r || (i <= mid && a[i].p <= a[j].p))
{
mark[k] = 0;
b[k ++] = a[i ++];
}
else
{
mark[k] = 1;
b[k ++] = a[j ++];
}
}
for (int i = l; i <= r; i ++)
{
if (mark[i] == 0) T.upd(b[i].v, 1);
else an[b[i].id] += T.qry(100000) - T.qry(b[i].v);
}
for (int i = l; i <= r; i ++) if (mark[i] == 0) T.upd(b[i].v, -1);
for (int i = r; i >= l; i --)
{
if (mark[i] == 0) T.upd(b[i].v, 1);
else an[b[i].id] += T.qry(b[i].v);
}
for (int i = l; i <= r; i ++) if (mark[i] == 0) T.upd(b[i].v, -1);
for (int i = l; i <= r; i ++) a[i] = b[i];
}
void CDQ(int l, int r)
{
if (l >= r) return ;
int mid = (l + r) >> 1;
CDQ(l, mid);
CDQ(mid + 1, r);
merge(l, mid, r);
}
int main()
{
n = in(), m = in();
for (int i = 1; i <= n; i ++)
{
a[i] = (Node) { 0, i, in(), i };
pos[a[i].v] = i;
}
for (int i = 1; i <= m; i ++)
{
int x = in();
ask[i] = pos[x];
a[pos[x]].t = n - i + 1;
}
sort(a + 1, a + n + 1);
CDQ(1, n);
for (int i = 1; i <= n; i ++) ans += an[a[i].id];
for (int i = 1; i <= m; i ++)
{
printf("%lld\n", ans);
ans -= an[ask[i]];
}
return 0;
}
/*
*/