Linxii's Blog
算法记录:数据结构Blur image

1.分块#

1.1总体思考#

1.2 题目记录#

1.2.1 LC 3943 递增后的数对数量 链接#

  题目要实现两种操作

    1. 区间加x
    1. 查询区间内x的数量

  对于区间操作来说,最容易想到的是线段树,但是线段树维护区间内每个数的数量非常麻烦,并且可能复杂度也不够好。分块在这种场景下较为合适,分块的区间加操作比线段树复杂度高一些,但是查询操作的复杂度更低,更加平衡。

  对于区间加操作与查询操作的时间复杂度都是根号级别的,分块的思想就是将数组划分为若干个大小为m\sqrt{m}的块,每个块内维护一些额外的信息来支持快速的区间加和查询操作。

题解代码
class Solution
{
    static constexpr int MX = 1'000'000'001;

public:
    vector<int> numberOfPairs(vector<int> &nums1, vector<int> &nums2, vector<vector<int>> &queries)
    {
        int n = nums1.size(), m = nums2.size();

        int B = sqrt(m * n);
        vector<tuple<int, int, unordered_map<int, int>, int>> blocks;

        for (int i = 0; i < m; i += B)
        {
            int r = min(i + B, m);

            unordered_map<int, int> cnt;

            for (int j = i; j < r; j++)
            {
                cnt[nums2[j]]++;
            }

            blocks.emplace_back(i, r, cnt, 0);
        }

        vector<int> ans;

        for (auto &q : queries)
        {
            if (q[0] == 1)
            {

                int l = q[1], r = q[2] + 1, val = q[3];

                for (auto &[bl, br, cnt, add] : blocks)
                {
                    if (bl >= r)
                    {
                        break;
                    }
                    if (br <= l|| add >= MX)
                    {
                        continue;
                    }

                    if (l <= bl && br <= r)
                    {
                        add = min(add + val, MX);
                        continue;
                    }

                    int L = max(bl, l), R = min(br, r);

                    for (int j = L; j < R; j++)
                    {
                        cnt[nums2[j]]--;
                         nums2[j] = min(nums2[j] + val, MX);
                        cnt[nums2[j]]++;
                    }
                }
            }
            else
            {
                int res = 0;
                for (auto &[l, r, cnt, add] : blocks)
                {
                    int tar = q[1] - add;
                    for (int x : nums1)
                    {
                        auto it = cnt.find(tar - x);
                        if (it != cnt.end())
                        {
                            res += it->second;
                        }
                    }
                }

                ans.push_back(res);
            }
        }

        return ans;
    }
};
cpp
算法记录:数据结构
https://linxii.top/blog/algorithm-5-ds
Author 林夕夕
Published at May 24, 2026
Comment seems to stuck. Try to refresh?✨