Question: There are 150000 numbers and 10000 operations. Change the number of I to x each time, and question the number of backward pairs after each operation.
Solution 1: Tree array + treap. Each element of the tree array is a tree. In this way, you can query the number of elements less than or equal to k in the previous item in lognlogn, when an element mage changes, you only need to delete the elements from the corresponding treap in the tree array. Each time you modify the reverse logarithm of the I-th element, we can see the number of reverse pairs after each operation. Because Treap is very mature, although the complexity is not high, the efficiency is very low.
Solution 2: Sqrt (N) multipart + sorting: count the number of elements whose I items are smaller than k, similar to spoj3261http: // www. spoj. pl/problems/RACETIME/; other operations are similar to solution 1. The code is small, the constant is small, and the efficiency is high.
# Include <cstdio> # include <algorithm> # include <cmath> using namespace std; const int maxn = 250010; const int maxm = 510; struct Block {int num [maxm], arr [maxm], len; bool dirty; void init (int n) {len = n; dirty = true;} int get (int k) {if (dirty) {for (int I = 1; I <= len; I ++) arr [I] = num [I]; sort (arr + 1, arr + len + 1 ); dirty = false;} int left = 1, right = len, ans = 0; while (left <= right) {int mid = (left + right)> 1; if (arr [mid] <= k) {ans = mid; left = mid + 1;} elseright = mid-1;} return ans;} void update (int I, int v) {if (v = num [I]) return; num [I] = v; dirty = true;} int query (int left, int right, int v) {int sum = 0; for (int I = left; I <= right; I ++) if (num [I] <= v) {sum ++ ;} return sum ;}} bk [maxm]; struct IndexTree {int ss [50020]; const static int N = 50010; void init () {for (int I = 1; I <= N; I ++) ss [I] = 0;} int lowbit (int k) {return (k &-k);} void inc (int I, int v) {while (I <= N) {ss [I] + = v; I + = lowbit (I) ;}} int get (int I) {int res = 0; while (I> 0) {res + = ss [I]; I-= lowbit (I) ;}return res ;}} all; int belong [maxn], id [maxn], M, n, m, x, y; int arr [maxn]; void build () {for (int I = 1; I * I <= n; I ++) M = I; int cnt = 0, len = M; for (int I = 1; I <= n; I ++) {if (len = M) {bk [++ cnt]. init (M); len = 0;} belong [I] = cnt; id [I] = ++ len; bk [cnt]. num [len] = arr [I];} bk [cnt]. len = len;} int query (int k, int c) {int sum = 0; int B = belong [k]; for (int I = 1; I <B; I ++) sum + = bk [I]. get (c); sum + = bk [B]. query (1, id [k], c); return sum;} long res; void init () {res = 0; scanf ("% d", & n ); for (int I = 1; I <= n; I ++) {scanf ("% d", arr + I); res + = I-1-all. get (arr [I]); all. inc (arr [I], 1) ;}} int cal (int k) {// calculate the number of inverse number pairs formed by element k. int a = all. get (arr [k]-1); int B = query (k, arr [k]-1); int c = query (k, arr [k]); return a-B + k-c;} int main () {init (); build (); scanf ("% d", & m); while (m --) {scanf ("% d", & x, & y); res-= cal (x); all. inc (arr [x],-1); all. inc (y, 1); int cnt = belong [x]; bk [cnt]. update (id [x], y); arr [x] = y; res + = cal (x); printf ("% lld \ n", res );} return 0 ;}
Uva11990 "Dynamic'' Inversion (Rujia Liu's Present 3: A Data Structure Contest Celebrating
The 100th Anniversary of Tsinghua University, Problem D)
This M is relatively large, so the first method is more efficient than the second method.
#include <cstdio>#include <cstring>#include <algorithm>#include <cstdlib>#include<cmath>#include<map>using namespace std;const int maxn = 200010;const int inf = 1 << 30;struct TreeNode {int key, pri;int left, right, size, num;void init() {left = right = 0;num = size = 1;pri = rand();}};TreeNode nodes[maxn * 25];int stack[maxn*25], top, cnt;int newnode() {int ret;if (top)ret = stack[--top];elseret = ++cnt;nodes[ret].init();return ret;}struct Treap {int root;void init() {root = cnt = top = 0;nodes[0].pri = -0x7FFFFFFF;}void push_up(int idx) {nodes[idx].size = nodes[nodes[idx].left].size+ nodes[nodes[idx].right].size + nodes[idx].num;}void leftRotate(int &root) {int tmp = nodes[root].right;nodes[root].right = nodes[nodes[root].right].left;nodes[tmp].left = root;push_up(root);push_up(tmp);root = tmp;}void rightRotate(int &root) {int tmp = nodes[root].left;nodes[root].left = nodes[nodes[root].left].right;nodes[tmp].right = root;push_up(root);push_up(tmp);root = tmp;}void insert(int k) {insert(k, root);}void insert(int k, int& root) {if (nodes[root].key == k) {nodes[root].num++;nodes[root].size++;return;}if (!root) {root = newnode();nodes[root].key = k;return;}if (k < nodes[root].key) {insert(k, nodes[root].left);if (nodes[nodes[root].left].pri > nodes[root].pri)rightRotate(root);} else {insert(k, nodes[root].right);if (nodes[nodes[root].right].pri > nodes[root].pri)leftRotate(root);}push_up(root);}void del(int k) {del(root, k);}void del(int &root, int k) {if (nodes[root].key == k) {if (!nodes[root].left && !nodes[root].right) {if (nodes[root].num == 1) {stack[top++] = root;root = 0;} else {nodes[root].num--;nodes[root].size--;}return;}if (nodes[nodes[root].left].pri > nodes[nodes[root].right].pri) {rightRotate(root);del(nodes[root].right, k);} else {leftRotate(root);del(nodes[root].left, k);}push_up(root);return;}if (k < nodes[root].key)del(nodes[root].left, k);elsedel(nodes[root].right, k);push_up(root);}int find(int k) {return find(root, k);}int find(int root, int k) {if (root == 0)return 0;if (nodes[root].key == k)return nodes[nodes[root].left].size + nodes[root].num;if (nodes[root].key > k)return find(nodes[root].left, k);elsereturn nodes[nodes[root].left].size + nodes[root].num + find(nodes[root].right, k);}} tree;int lowbit(int k) {return (k & -k);}struct node {int len;Treap tree;void init() {tree.init();}int get(int k) {return tree.find(k);}void update(int v) {if (v > 0)tree.insert(v);elsetree.del(-v);}};struct IndexTree {int ss[maxn],N;void init(int n) {N=n;memset(ss, 0, sizeof(ss));}void inc(int i, int v) {while (i <= N) {ss[i] += v;i += lowbit(i);}}int get(int i) {int res = 0;while (i > 0) {res += ss[i];i -= lowbit(i);}return res;}};node ss[maxn];int pos[maxn], arr[maxn], m, n, x;IndexTree all, now;long long res;void init() {now.init(n);all.init(n);for (int i = 1; i <= n; i++)ss[i].init();}void update(int i, int v) {while (i <= n) {ss[i].update(v);i += lowbit(i);}}int query(int i, int v) {int res = 0;while (i > 0) {res += ss[i].get(v);i -= lowbit(i);}return res;}void build() {res = 0;for (int i = 1; i <= n; i++) {scanf("%d", &x);pos[x] = i;arr[i] = x;res += i - 1 - all.get(x);all.inc(x, 1);update(i, x);now.inc(i, 1);}}int cal(int k) {int a = all.get(arr[k] - 1);int b = query(k, arr[k] - 1);k = now.get(k);return a - b + k-b-1;}int main() {while (scanf("%d %d", &n, &m) != EOF) {init();build();while (m--) {printf("%lld\n",res);scanf("%d", &x);res -= cal(pos[x]);all.inc(x, -1);now.inc(pos[x], -1);update(pos[x], -x);}}return 0;}