P3157 动态逆序对 题解

逆序对的定义 \(\{(i,j)|i<j\and a_i>a_j\}\) 那么这道题目加了时间的一维进去。我们可以想成三维。

对每一个点有一个坐标 \((A_i, B_i, C_i)\)\(A_i\) 的就是 \(i\)\(B_i\) 就是 \(a_i\)\(C_i\) 就是 \(\text{tim}_i\)。其中 \(\text{tim}_i\) 表示 \(i\) 被删除的时间。

考虑每一个点对答案的贡献,逆序对是对,所以我可以只考察 \(a_i\) 更大的那个,这样不重复不遗漏。

那么假如说对于第 \(i\) 个点,我们肯定要求 \(j>i\) 并且 \(a_i>a_j\) 并且 \(\text{tim}_j\ge\text{tim}_i\)。求出这样的 \(j\) 的个数后那么答案对 \(1\)\(\text{tim}_i-1\) 都会有贡献。

那么这明显是一个 cdq 分治。直接套用 cdq 分治即可。

#include<bits/stdc++.h>
#define rep(I, J, K) for(int I = (int)J; I <= (int)K; ++I)
#define per(I, J, K) for(int I = (int)J; I >= (int)K; --I)
using namespace std;
const int N = 5e5 + 10;

typedef long long ll;
int n, m, a[N], b[N];
ll ans[N];

struct Point {
    int x, y, z;
    bool operator < (const Point &point) const {
        return (y == point.y) ? z > point.z : y < point.y;
    }
}p[N];
int tim[N];

struct Fenwick_Tree {
    ll val[N];
    int lowbit(int x) {return x & -x;}
    void insert(int x, int va) {
        while(x <= m + 1) {
            val[x] += va;
            x += lowbit(x);
        }
    }
    int Query(int x) {
        if(x < 0) return 0;
        int res = 0;
        while(x) {
            res += val[x];
            x -= lowbit(x);
        }
        return res;
    }
    int query(int l, int r) {
        return Query(r) - Query(l - 1);
    }
}bit;

void solve(int l, int r) {
    if(l == r) return;
    int mid = l + r >> 1;
    solve(l, mid); solve(mid + 1, r);
    int j = mid + 1;
    rep(i, l, mid) {
        while(j <= r && p[j].y < p[i].y) bit.insert(p[j].z, 1), ++j;
        ll tmp = bit.query(p[i].z, m + 1);
        // if(i == 2) cerr << '*' << l << ' ' << r << ' ' << tmp << ' ' << p[i].x << ' ' << p[i].z << ' ' << j << ' ' << p[4].y << ' ' << p[4].z << endl;
        ans[1] += tmp, ans[p[i].z + 1] -= tmp;
    }
    rep(i, mid + 1, j - 1) bit.insert(p[i].z, -1);
    int i = mid;
    per(j, r, mid + 1) {
        while(i >= l && p[i].y > p[j].y) bit.insert(p[i].z, 1), --i;
        ll tmp = bit.query(p[j].z + 1, m + 1);
        ans[1] += tmp, ans[p[j].z + 1] -= tmp;
    }
    per(k, mid, i + 1) bit.insert(p[k].z, -1);
    sort(p + l, p + r + 1);
}

int main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n >> m;
    rep(i, 1, n) cin >> a[i], b[a[i]] = i;
    rep(i, 1, m) {
        int t;
        cin >> t;
        tim[t] = i;
    }
    rep(i, 1, n) if(tim[i] == 0) tim[i] = m;
    rep(i, 1, n) p[i] = {i, a[i], tim[a[i]]};
    solve(1, n);
    rep(i, 1, m) ans[i] += ans[i - 1];
    rep(i, 1, m) cout << ans[i] << '\n';
    return 0;
}
posted @ 2026-09-10 00:44  Mercury_City  阅读(7)  评论(0)    收藏  举报