【LG1975】[國家集訓隊]排隊
阿新 • • 發佈:2018-12-14
【LG1975】[國家集訓隊]排隊
題面
題解
又是一個偏序問題
顯然\(CDQ\)
交換操作不好弄怎麼辦?
可以看成兩次刪除兩次插入
排序問題要注意一下
程式碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <vector> using namespace std; namespace IO { const int BUFSIZE = 1 << 20; char ibuf[BUFSIZE], *is = ibuf, *it = ibuf; inline char gc() { if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin); return *is++; } } inline int gi() { register int data = 0, w = 1; register char ch = 0; while (ch != '-' && (ch > '9' || ch < '0')) ch = IO::gc(); if (ch == '-') w = -1 , ch = IO::gc(); while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::gc(); return w * data; } const int MAX_N = 22005; struct Node { int x, y, z, w, id; } t[MAX_N << 2], tmp[MAX_N << 2]; bool cmp_y(Node a, Node b) { return (a.y == b.y) ? (a.z < b.z) : (a.y < b.y); } int N, M, tot, X[MAX_N], a[MAX_N], c[MAX_N], ans[MAX_N]; inline int lb(int x) { return x & -x; } void add(int x, int v) { while (x <= N) c[x] += v, x += lb(x); } int sum(int x) { int res = 0; while (x > 0) res += c[x], x -= lb(x); return res; } void Div(int l, int r) { if (l == r) return ; int mid = (l + r) >> 1; for (int i = l; i <= r; i++) if (t[i].x <= mid) add(t[i].z, t[i].w); else ans[t[i].id] += t[i].w * (sum(N) - sum(t[i].z)); for (int i = l; i <= r; i++) if (t[i].x <= mid) add(t[i].z, -t[i].w); for (int i = r; i >= l; i--) if (t[i].x <= mid) add(t[i].z, t[i].w); else ans[t[i].id] += t[i].w * sum(t[i].z - 1); for (int i = l; i <= r; i++) if (t[i].x <= mid) add(t[i].z, -t[i].w); int t1 = l - 1, t2 = mid; for (int i = l; i <= r; i++) if (t[i].x <= mid) tmp[++t1] = t[i]; else tmp[++t2] = t[i]; for (int i = l; i <= r; i++) t[i] = tmp[i]; Div(l, mid); Div(mid + 1, r); } int main () { N = gi(); for (int i = 1; i <= N; i++) X[i] = a[i] = gi(); sort(&X[1], &X[N + 1]); int size = unique(&X[1], &X[N + 1]) - X - 1; for (int i = 1; i <= N; i++) a[i] = lower_bound(&X[1], &X[size + 1], a[i]) - X; for (int i = 1; i <= N; i++) t[++tot] = (Node){tot, i, a[i], 1, 0}; N = size; M = gi(); for (int i = 1; i <= M; i++) { int x = gi(), y = gi(); t[++tot] = (Node){tot, x, a[x], -1, i}; t[++tot] = (Node){tot, y, a[y], -1, i}; t[++tot] = (Node){tot, x, a[y], +1, i}; t[++tot] = (Node){tot, y, a[x], +1, i}; swap(a[x], a[y]); } sort(&t[1], &t[tot + 1], cmp_y); Div(1, tot); printf("%d\n", ans[0]); for (int i = 1; i <= M; i++) printf("%d\n", ans[i] += ans[i - 1]); return 0; }