记录编号 572290 评测结果 AAAAAAAAAA
题目名称 [CQOI2011]动态逆序对 最终得分 100
用户昵称 Gravatarlihaoze 是否通过 通过
代码语言 C++ 运行时间 1.013 s
提交时间 2022-06-30 12:03:12 内存使用 7.64 MiB
显示代码纯文本
#include <bits/stdc++.h>

using i64 = long long;

const int N = 2e5+10;
int n, m;

struct rec { int v, del, ans; } a[N];

int c[N];

int lowbit(int x) { return x & -x; }

void add(int x, int y) {
    for (; x <= n + 1; x += lowbit(x)) c[x] += y;
}

int ask(int x) {
    int t = 0;
    for (; x; x -= lowbit(x)) t += c[x];
    return t;
}

int rev[N];
i64 res;

void cdqdiv(int l, int r) {
    if (r - l == 1) return;
    int mid = l + r >> 1;
    cdqdiv(l, mid), cdqdiv(mid, r);

    // 删除 a[i] 之前,匹配的元素的数量
    int i = l + 1, j = mid + 1;
    while (i <= mid) {
        while (a[i].v > a[j].v && j <= r) 
            add(a[j ++].del, 1);
        a[i].ans += ask(m + 1) - ask(a[i].del), ++ i;
    }

    // 复原
    i = l + 1, j = mid + 1;
    while (i <= mid) {
        while (a[i].v > a[j].v && j <= r) 
            add(a[j ++].del, -1);
        ++ i;
    }

    // 删除 a[j] 之前,匹配的元素的数量
    i = mid, j = r;
    while (j > mid) { 
        while (a[i].v > a[j].v && i > l)
            add(a[i --].del, 1);
        a[j].ans += ask(m + 1) - ask(a[j].del), -- j;
    }
    // 复原
    i = mid, j = r;
    while (j > mid) { 
        while (a[i].v > a[j].v && i > l)
            add(a[i --].del, - 1);
        -- j;
    }

    std::sort(a + l + 1, a + r + 1, [&](rec a, rec b) {
        return a.v < b.v;
    });
}

int main() {
    freopen("inverse.in", "r", stdin); 
    freopen("inverse.out", "w", stdout);
    std::cin >> n >> m;
    for (int i = 1; i <= n; ++ i) {
        std::cin >> a[i].v;
        rev[a[i].v] = i;
    }
    for (int i = 1; i <= m; ++ i) {
        int del;
        std::cin >> del;
        a[rev[del]].del = i;
    }
    for (int i = 1; i <= n; ++ i) 
        if (a[i].del == 0) a[i].del = m + 1;

    // 求初始逆序对
    for (int i = 1; i <= n; ++ i) {
        res += ask(n + 1) - ask(a[i].v);
        add(a[i].v, 1);
    }   
    for (int i = 1; i <= n; ++ i) 
        add(a[i].v, -1);

    // cdqdiv
    cdqdiv(0, n);
    std::sort(a + 1, a + n + 1, [&](rec a, rec b) {
        return a.del < b.del;
    });
    for (int i = 1; i <= m; ++ i) 
        std::cout << res << '\n', res -= a[i].ans;
    return 0;
}