二维莫队
二维莫队,顾名思义就是每个状态有四个方向可以扩展。
二维莫队每次移动指针要操作一行或者一列的数,具体实现方式与普通的一维莫队类似,这里不再赘述。这里重点讲块长选定部分。
块长选定
记询问次数为 \(q\),当前矩阵的左上角坐标为 \((x_1,\ y_1)\),右下角坐标为 \((x_2,\ y_2)\),取块长为 \(B\)。
那么指针 \(x_1\) 移动了 \(\Theta(q\cdot B)\) 次,而指针 \(y_2\) 移动了 \(\Theta(n^4\cdot B^{-3})\) 次。
所以只需令 \(q\cdot B=n^4\cdot B^{-3}\),即 \(B=n\cdot q^{-\frac 14}\) 即可。
注意这样计算 \(B\) 的结果 可能为 \(0\),注意特判。
最终,计算部分时间复杂度是 \(\Theta(n^2\cdot q^{\frac 34})\),加上对询问的排序过程,总时间复杂度为 \(\Theta(n^2\cdot q^{\frac 34}+q\log q)\)。
例题 1
BZOJ 2639 矩形计算
输入一个 \(n\times m\) 的矩阵,矩阵的每一个元素都是一个整数,然后有 \(q\) 个询问,每次询问一个子矩阵的权值。矩阵的权值是这样定义的,对于一个整数 \(x\),如果它在该矩阵中出现了 \(p\) 次,那么它给该矩阵的权值就贡献 \(p^2\)。
数据范围:\(1\leq n,\ m\leq 200\),\(0\leq q\leq 10^5\),\(|\) 矩阵元素大小 \(| \leq 2\times 10^9\)。
解题思路
先离散化,二维莫队时用一个数组记录每个数当前出现的次数即可。
示例代码
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
|
例题 2
洛谷 P1527 [国家集训队] 矩阵乘法
给你一个 \(n\times n\) 的矩阵,\(q\) 次询问,每次询问一个子矩形的第 \(k\) 小数。
数据范围:\(1\leq n\leq 500\),\(1\leq q\leq 6\times 10^4\),\(0\leq a_{i,j}\leq 10^9\)。
首先和上一题一样,需要离散化整个矩阵。但是需要注意,本题除了需要对数值进行分块,还需要对数值的值域进行分块,才能求出答案。
这里还需要用到奇偶化排序进行优化,具体内容请见 普通莫队算法。
对于本题而言,时间限制不那么宽,注意代码常数的处理。取的块长计算值普遍较小,\(n,\ q\) 都取最大值时块长大约在 \(11\) 左右,可以直接设定为常数来节约代码耗时。
示例代码
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
|
本页面的全部内容在 小熊老师 - 莆田青少年编程俱乐部 0594codes.cn 协议之条款下提供,附加条款亦可能应用