P3157 [CQOI2011]动态逆序对 (树套树/树状数组套主席树)

题意:动态计算逆序对,给出n,m,n是数组大小,m是删的数的个数,要求每次删完数后剩下的逆序对个数。

思路:若普通主席树的话,每次删一个数,则要更新后面n个数的大小,复杂度nlogn,直接爆炸,所以考虑一种可以单点修改和区间查询的数据结构,线段树或树状数组都可以,不过显然树状数组好写,所以用树状数组来代替主席树的root数组,求出总的逆序对后,每次删除一个数m就减去从1到m-1求大于m的数的个数,然后再减去从m+1到n的小于m的数的个数。

没用快读,不过开o2可过

#include<bits/stdc++.h>
#define ll long long
#define lowbit(x) ((x)&(-x))
using namespace std;
const int N = 1e5 + 10;
int n, m, root[N], cnt, pos[N];
ll ans;
struct node {
    int l, r, num;
} zxs[N * 300];
void add(int l, int r, int &now, int pos, int k) {
    if(!now)
        now = ++cnt;
    zxs[now].num += k;
    if(l == r)
        return;
    int m = (l + r) >> 1;
    if(pos <= m)
        add(l, m, zxs[now].l, pos, k);
    else
        add(m + 1, r, zxs[now].r, pos, k);
}
void ins(int i, int x, int v) {
    for (int j = i; j <= n; j += lowbit(j))
        add(1, n, root[j], x, v);
}
int ask(int p, int l, int r, int ql, int qr) {
    if(ql <= l && r <= qr)
        return zxs[p].num;
    int m = (l + r) / 2, res = 0;
    if(ql <= m)
        res += ask(zxs[p].l, l, m, ql, qr);
    if(qr > m)
        res += ask(zxs[p].r, m + 1, r, ql, qr);
    return res;
}
ll sum(int x, int L, int R) {
    ll ans = 0;
    for(int i = x; i > 0; i -= lowbit(i))
        ans += ask(root[i], 1, n, L, R);
    return ans;
}
ll calc(int l, int r, int L, int R) {
    if(l > r || L > R)
        return 0;
    return sum(r, L, R) - sum(l - 1, L, R);
}
int main() {
    scanf("%d%d", &n, &m);
    for(int v, i = 1; i <= n; i++) {
        scanf("%d", &v), pos[v] = i;
        ans += calc(1, i - 1, v + 1, n);
        ins(i, v, 1);
    }
    for(int x, i = 1; i <= m; i++) {
        scanf("%d", &x);
        printf("%lld\n", ans);
        ans -= (calc(1, pos[x] - 1, x + 1, n) + calc(pos[x] + 1, n, 1, x - 1));
        ins(pos[x], x, -1);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值