$\Large \color{Green}{Describe}$

题意 :对于一个长度为$n$$(n\le 200000)$的序列进行$q$$(q \le 50000)$次操作,每次操作都是交换序列中的某两个数。对于每一个操作,回答当前序列中有多少个逆序对。

本题是一个三维偏序问题,所求即为满足$pos_i>pos_j 且 val_i<val_j$$或$$pos_i<pos_j 且 val_i>val_j$的$(i,j)$​的对数。

我们考虑每次交换操作,可以拆成两个删除和两个插入,先减去贡献,然后在原位置删除,再交换两个值的$pos$,之后在新位置插入,再加上现在的贡献,这样就做完了$……$吗?

写出来会发现样例都过不了,原因是我们在这样处理时会额外计算一些贡献

  • 当交换后这两个数产生了一对逆序对时,$ans$- -
  • 当交换后这两个数减少了一对逆序对时,$ans$++

因为当交换后产生了一对逆序对时,加贡献会把这一对加两遍,同理减少了一对时减贡献会减两遍。

然后就是上树状数组套动态开点权值线段树,时空复杂度均是$\Theta(nlog^2_n)$

$\Large Code:$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#pragma region revive
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <bitset>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define inl inline
#define re register int
#define fa(x) t[x].fa
#define son(x,y) t[x].child[y]
#define ls(x) t[x].child[0]
#define rs(x) t[x].child[1]
#define ll long long
const int inf = 0x3f3f3f3f;
#define lowbit(x) ((x) & (-x))
using namespace std;
#ifndef _DEBUG
#define getchar() (*(IOB.in.p++))
#define putchar(c) (*(IOB.out.p++)=(c))
#define io_eof() (IOB.in.p>=IOB.in.pend)
struct IOBUF { struct { char buff[1 << 26], *p, *pend; }in; struct { char buff[1 << 26], *p; }out; IOBUF() { in.p = in.buff; out.p = out.buff; in.pend = in.buff + fread(in.buff, 1, 1 << 26, stdin); }~IOBUF() { fwrite(out.buff, 1, out.p - out.buff, stdout); } }IOB;
#endif
template<typename IO>
inl void write(IO x) {
if (x == 0) return (void)putchar('0');
if (x < 0)putchar('-'), x = -x;
static char buf[30];
char* p = buf;
while (x) {
*(p++) = x % 10 + '0';
x /= 10;
}
while (p > buf)putchar(*(--p));
}
inl void writestr(const char *s) { while (*s != 0)putchar(*(s++)); }
template<typename IO>inl void writeln(IO x) { write(x), putchar('\n'); }
template<typename IO>inl void writesp(IO x) { write(x), putchar(' '); }
inl int readstr(char *s) {
char *begin = s, c = getchar();
while (c < 33 || c>127) {
c = getchar();
}
while (c >= 33 && c <= 127) {
*(s++) = c;
c = getchar();
}
*s = 0;
return s - begin;
}
template<typename IO>
inl IO read() {
IO x = 0;
register bool w = 0;
register char c = getchar();
while (c > '9' || c < '0') {
if (c == '-') w = 1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return w ? -x : x;
}
#pragma endregion
#undef ls
#undef rs
#define ls(x) t[x].l
#define rs(x) t[x].r
int root[1000001], cnt, pos[1000001], tmpl[51], tmpr[51], cntl, cntr, n;
struct node {
int w, l, r;
}t[20000001];
inl void maintain(int x) {
t[x].w = t[ls(x)].w + t[rs(x)].w;
}
inl void change(int &k, int l, int r, int p, int w) {
if (!k)k = ++cnt;
if (l == r)return (void)(t[k].w += w);
re mid = l + r >> 1;
if (p <= mid)change(ls(k), l, mid, p, w);
else change(rs(k), mid + 1, r, p, w);
maintain(k);
}
inl int query(int l, int r, int x, bool op) {
cntl = cntr = 0;
for (re i = l - 1; i; i -= lowbit(i)) tmpl[++cntl] = root[i];
for (re i = r; i; i -= lowbit(i))tmpr[++cntr] = root[i];
l = 1, r = n;
re mid, ans = 0;
while (l != r) {
mid = l + r >> 1;
if (x <= mid) {
if (op) {
for (re i = 1; i <= cntl; i++)ans -= t[rs(tmpl[i])].w;
for (re i = 1; i <= cntr; i++)ans += t[rs(tmpr[i])].w;
}
for (re i = 1; i <= cntl; i++)tmpl[i] = ls(tmpl[i]);
for (re i = 1; i <= cntr; i++)tmpr[i] = ls(tmpr[i]);
r = mid;
}
else {
if (!op) {
for (re i = 1; i <= cntl; i++)ans -= t[ls(tmpl[i])].w;
for (re i = 1; i <= cntr; i++)ans += t[ls(tmpr[i])].w;
}
for (re i = 1; i <= cntl; i++)tmpl[i] = rs(tmpl[i]);
for (re i = 1; i <= cntr; i++)tmpr[i] = rs(tmpr[i]);
l = mid + 1;
}
}
return ans;
}
signed main() {
n = read<int>();
re m = read<int>(), x, y;
ll ans = 0;
for (re i = 1; i <= n; i++) {
pos[i] = i;
for (re j = i; j <= n; j += lowbit(j)) change(root[j], 1, n, i, 1);
}
while (m--) {
x = read<int>(), y = read<int>();
if (x == y) {
writeln(ans);
continue;
}
ans -= query(1, pos[x] - 1, x, 1) + query(pos[x] + 1, n, x, 0);
ans -= query(1, pos[y] - 1, y, 1) + query(pos[y] + 1, n, y, 0);
for (re i = pos[x]; i <= n; i += lowbit(i))change(root[i], 1, n, x, -1);
for (re i = pos[y]; i <= n; i += lowbit(i))change(root[i], 1, n, y, -1);
swap(pos[x], pos[y]);
for (re i = pos[x]; i <= n; i += lowbit(i))change(root[i], 1, n, x, 1);
for (re i = pos[y]; i <= n; i += lowbit(i))change(root[i], 1, n, y, 1);
ans += query(1, pos[x] - 1, x, 1) + query(pos[x] + 1, n, x, 0);
ans += query(1, pos[y] - 1, y, 1) + query(pos[y] + 1, n, y, 0);
ans -= (pos[x] > pos[y] && x < y) || (pos[x] < pos[y] && x > y);
ans += (pos[x] > pos[y] && x > y) || (pos[x] < pos[y] && x < y);
writeln(ans);
}
}