Uva 11990 "Dynamic" Inversion(树状数组 + 数据结构分块)

来源:互联网 发布:出国留学的意义 知乎 编辑:程序博客网 时间:2024/05/20 23:03
题意:给一个1 ~ n的排列,有m次删除操作,问每次删除前该序列有多少逆序对


思路:预处理原来总共有多少逆序对,树状数组即可,求出以每个数为逆序对有多少个,删除的时候,先用剩余的逆序对数减去以该数形成的逆序对数,然后看删除的数有多少与该数形成逆序对,再加回去,可以使用分块的方法,快速查询有多少删除的数与其形成逆序对,每次删除的数加在一个新数组上,对新数组分块查找就行了


#include<cstdio>#include<cstring>#include<algorithm>typedef long long ll;const int maxn = 2 * 1e5 + 10;const int sz = 2345;using namespace std;int block[maxn / sz + 1][sz];int a[maxn], id[maxn];int inv[maxn];int C[maxn];int n, m, d;int query(int l, int r, int v, int op) {    if(l > r) return 0;    int lb = l / sz, rb = r / sz;    int k1 = 0, k2 = 0;    if(lb == rb) {        for(int i = l; i <= r; i++) {            if(a[i] && a[i] < v) k1++;            if(a[i] > v) k2++;        }    } else {        for(int i = l; i < (lb + 1) * sz; i++) {            if(a[i] && a[i] < v) k1++;            if(a[i] > v) k2++;        }        for(int i = rb * sz; i <= r; i++) {            if(a[i] && a[i] < v) k1++;            if(a[i] > v) k2++;        }        for(int b = lb + 1; b < rb; b++) {            int c1 = lower_bound(block[b], block[b] + sz, v) - block[b];            int c2 = upper_bound(block[b], block[b] + sz, 0) - lower_bound(block[b], block[b] + sz, 0);            k1 += c1 - c2;            int ind = upper_bound(block[b], block[b] + sz, v) - block[b];            k2 += sz - ind;        }    }    if(op == 1) return k1;    if(op == 2) return k2;}void update(int p, int x) {    if(a[p] == x) return ;    int old = a[p], pos = 0, *B = &block[p / sz][0];    a[p] = x;    while(B[pos] < old) pos++; B[pos] = x;    if(x > old) {        while(pos < sz - 1 && B[pos] > B[pos + 1]) {            swap(B[pos], B[pos + 1]); pos++;        }    } else {        while(pos && B[pos] < B[pos - 1]) {            swap(B[pos], B[pos - 1]); pos--;        }    }}int sum(int *C, int i) {    int c = 0;    while(i) {        c += C[i];        i -= i & -i;    }    return c;}void update(int *C, int i) {    while(i <= n) {        C[i]++;        i += i & -i;    }}int main() {    while(scanf("%d %d", &n, &m) != EOF) {        memset(inv, 0, sizeof inv);        memset(C, 0, sizeof C);        for(int i = 1; i <= n; i++) {            scanf("%d", &a[i]);            id[a[i]] = i;        }        ll tal = 0;        for(int i = n; i >= 1; i--) {            int g = sum(C, a[i] - 1);            tal += g;            inv[i] += g;            inv[i] += i + g - a[i];            update(C, a[i]);        }        memset(a, 0, sizeof a);        while(m--) {            printf("%lld\n",tal);            scanf("%d", &d);            tal -= inv[id[d]];            tal += query(id[d] + 1, n, d, 1);            tal += query(1, id[d] - 1, d, 2);            update(id[d], d);        }    }    return 0;}


0 0