CF1093E.Intersection of Permutations 题解 分块套树状数组

题目链接:https://codeforces.com/problemset/problem/1093/E

解题思路来自 oi.wiki

这道题 与其说是 “分块 套 树状数组”,不如说是 “树状数组 套 分块 (再)套 树状数组”。因为分块还需要用树状数组维护一个前缀和。

如果直接 分块 + 树状数组,时间复杂度是 \(O(m \sqrt{n} \log n)\),会超时。

如果再在分块外面维护一个树状数组,则时间复杂度降为 \(O(m \cdot ( \sqrt{n} + \log ( \sqrt{n} ) \log n ))\),可以通过本题。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5, maxb = sqrt(maxn) + 5;

int n, m, q, blo, N, tr[maxb][maxn], a[maxn], b[maxn], pa[maxn], pb[maxn];

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

int id(int p) {
    return (p - 1) / blo + 1;
}

// 查询a[1..x] 有多少个数字在 b[1..y]
int query(int x, int y) {
//    printf("\tquery (%-2d , %2d) = ", x, y);
    int res = 0;
    for (; x % blo; x--)
        if (pb[a[x]] <= y)
            res++;
    if (!x) return res;
    for (int i = id(x); i; i -= lowbit(i))
        for (int j = y; j; j -= lowbit(j))
            res += tr[i][j];
//    cout << res << endl;
    return res;
}

// 查询a[1..x] 有多少个数字在 b[l..r]
int query(int x, int l, int r) {
    return query(x, r) - query(x, l-1);
}

// 查询a[l1..r1] 有多少个数字在 b[l2..r2]
int query(int l1, int r1, int l2, int r2) {
    return query(r1, l2, r2) - query(l1-1, l2, r2);
}

// +1/-1(新增/解绑)a[x] -- b[y] 的关系
void add(int x, int y, int val) {
    for (int i = id(x); i <= N; i += lowbit(i))
        for (int j = y; j <= n; j += lowbit(j))
            tr[i][j] += val;
}

int main() {
    scanf("%d%d", &n, &m);
    blo = sqrt(n);
    N = id(n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", a+i);
        pa[ a[i] ] = i;
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d", b+i);
        pb[ b[i] ] = i;
    }
    for (int i = 1; i <= n; i++)
        add(pa[i], pb[i], 1);
    for (int i = 0, op; i < m; i++) {
        scanf("%d", &op);
        if (op == 1) {
            int l1, r1, l2, r2;
            scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
            printf("%d\n", query(l1, r1, l2, r2));
        }
        else {
            int x, y;
            scanf("%d%d", &x, &y);
            int v1 = b[x], v2 = b[y];
            add(pa[v1], x, -1);
            add(pa[v2], y, -1);
            add(pa[v1], y, 1);
            add(pa[v2], x, 1);
            pb[v1] = y;
            pb[v2] = x;
            swap(b[x], b[y]);
        }
    }
    return 0;
}
posted @ 2026-01-08 23:03  quanjun  阅读(9)  评论(0)    收藏  举报