COGS-1715 [CQOI2011]动态逆序对(树状数组+线段树)

来源:互联网 发布:口袋助理软件 编辑:程序博客网 时间:2024/05/16 10:04

1715. [CQOI2011]动态逆序对

★★★   输入文件:inverse.in   输出文件:inverse.out   简单对比
时间限制:2 s   内存限制:128 MB

【题目描述】

对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

【输入格式】

输入第一行包含两个整数nm,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
 

【输出格式】

 
输出包含m行,依次为删除每个元素之前,逆序对的个数。

【样例输入】

5 4  1  5  3  4  2  5  1  4  2  

【样例输出】

5  2  2  1    样例解释  (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。  

【提示】


N<=100000 M<=50000

题解:树状数组+线段树

首先用树状数组求一下原始的逆序对,每次删除一个数x的时候,ans-=x后面比x小的数+x前面比x大的数

当然这样算会有重复,因为有些数有可能已经删去了,因此可以用一个二维变量(i,a[i])记录已经删去的值,用树状数组+线段树维护一下即可。时间复杂度O(nlog^2n)

(其实可以用CDQ分治来写,,,不过还是树写起来爽

#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MX = 1e5 + 5;const int MXM = MX * 80;int n, m, cnt;int sum[MXM], ls[MXM], rs[MXM];int a[MX], fa[MX];LL f[MX];struct Tree {    int n;    vector <LL> T;    void init(int _n) {        T.clear();        n = _n;        T.resize(n + 1);    }    void add(int x, LL v) {        for (int i = x; i <= n; i += i & -i) T[i] += v;    }    LL sum(int x) {        if (x > n) x = n;        LL ret = 0;        for (int i = x; i > 0; i -= i & -i) ret += T[i];        return ret;    }} T;void update(int p, int val, int l, int r, int prt, int &rt) {    rt = ++cnt;    ls[rt] = ls[prt]; rs[rt] = rs[prt];    sum[rt] = sum[prt] + 1;    if (l == r) return;    int m = (l + r) >> 1;    if (p <= m) update(p, val, l, m, ls[prt], ls[rt]);    else update(p, val, m + 1, r, rs[prt], rs[rt]);}int query(int L, int R, int l, int r, int rt) {    if (L <= l && R >= r) return sum[rt];    int m = (l + r) >> 1, ret = 0;    if (L <= m) ret += query(L, R, l, m, ls[rt]);    if (R > m) ret += query(L, R, m + 1, r, rs[rt]);    return ret;}struct BTree {    int n;    vector <int> T;    void init(int _n) {        T.clear();        n = _n;        T.resize(n + 1);    }    void add(int x, int y, int v) {        for (int i = x; i <= n; i += i & -i) update(y, v, 1, n, T[i], T[i]);    }    int sum(int x, int l, int r) {        if (x > n) x = n;        int ret = 0;        for (int i = x; i > 0; i -= i & -i) ret += query(l, r, 1, n, T[i]);        return ret;    }} bt;int main() {    //freopen("in.txt", "r", stdin);    freopen("inverse.in", "r", stdin);    freopen("inverse.out", "w+", stdout);    scanf("%d%d", &n, &m);    T.init(n);    bt.init(n);    for (int i = 1; i <= n; i++) scanf("%d", &a[i]), fa[a[i]] = i;    LL ans = 0;    for (int i = n; i > 0; i--) {        f[i] = T.sum(a[i]);        ans += f[i];        T.add(a[i], 1);    }    for (int i = 1, x; i <= m; i++) {        printf("%lld\n", ans);        scanf("%d", &x);        int index = fa[x];        ans -= 2 * f[index] + index - x;        ans += bt.sum(index, x, n);        ans += bt.sum(n, 1, x) - bt.sum(index, 1, x);        bt.add(index, x, 1);    }    return 0;}




阅读全文
0 0
原创粉丝点击