OSDN Git Service

Update cdq-divide.md
authorhsfzLZH1 <34390285+hsfzLZH1@users.noreply.github.com>
Wed, 3 Oct 2018 04:21:01 +0000 (12:21 +0800)
committerGitHub <noreply@github.com>
Wed, 3 Oct 2018 04:21:01 +0000 (12:21 +0800)
docs/misc/cdq-divide.md

index d1a13e5..7ebe6d8 100644 (file)
@@ -67,7 +67,7 @@ $a[l \cdots mid]\leq a[mid+1 \cdots r]$ 是只能算出 $l$ 对 $r$ 的贡献的
 
 题目大意 : 给出一个序列 ($N$个数字) , 操作包括单点修改, 区间查询。
 
-再次提一下 $CDQ$ 分治的主要思想:
+再次提一下 CDQ 分治的主要思想:
 
 - 求左边区间的贡献
 - 求右边区间的贡献
@@ -78,7 +78,7 @@ $a[l \cdots mid]\leq a[mid+1 \cdots r]$ 是只能算出 $l$ 对 $r$ 的贡献的
 在我们使用树状数组或者线段树解决这道问题的时候, 基于的是前缀和和分治的思想, 这里稍微有点不同。我们想,**一个修改必定会影响它后面的查询**, 当我们把原数组也视作修改的时候,
 整个就变成了**哪个修改会影响哪个查询**的问题。
 
-再想一下 $CDQ$ 分治的思想, 我们可不可以求左半边对右半边的贡献呢? 先假设一个区间 $l,r$, 假如 $l$ 到 $mid$ 的操作都是在 $mid+1$ 到 $r$ 前面做的 (也就是左半边所有的时间都小于右半边的时间), 那么 $l$ 到 $mid$ 的修改必定会影响到 $mid+1$ 到 $r$ 的查询。
+再想一下 CDQ 分治的思想, 我们可不可以求左半边对右半边的贡献呢? 先假设一个区间 $l,r$, 假如 $l$ 到 $mid$ 的操作都是在 $mid+1$ 到 $r$ 前面做的 (也就是左半边所有的时间都小于右半边的时间), 那么 $l$ 到 $mid$ 的修改必定会影响到 $mid+1$ 到 $r$ 的查询。
 
 ![](https://s1.ax1x.com/2018/09/08/iPaVAI.png)
 
@@ -90,15 +90,15 @@ $a[l \cdots mid]\leq a[mid+1 \cdots r]$ 是只能算出 $l$ 对 $r$ 的贡献的
 
 ![](https://s1.ax1x.com/2018/09/08/iPaGEn.png)
 
-(注意,$time$ 为操作的时间,$point$ 为右端点的位置,$mode$ 为查询 ($Q$) 或者修改 ($C$)。以下的 $n$ 为操作的总数, 包括把查询拆分和原序列)
+(注意,$time$ 为操作的时间,$point$ 为右端点的位置,$mode$ 为查询 (Q) 或者修改 (C)。以下的 $n$ 为操作的总数, 包括把查询拆分和原序列)
 
-我们对左半边和右半边的区间的右端点进行排序以后, 左半边的时间还是要小于右半边最低的时间。我们可以很容易想到, $1$ 号 的 右端点是 $1$, 它对右半边的所有查询都会产生贡献。而 $2$ 号的右端点是 $3$右半边, 它只能对
+我们对左半边和右半边的区间的右端点进行排序以后, 左半边的时间还是要小于右半边最低的时间。我们可以很容易想到, $1$ 号 的 右端点是 $1$, 它对右半边的所有查询都会产生贡献。而 $2$ 号的右端点是 $3$ 右半边, 它只能对
 右半边的 $2,3,4$ 号有贡献。也就是说, 我们只需要每一次比较 $left$ 是否小于 $right$ (其中 $left$ 为 $1$ 到 $mid$,$right$ 为 $mid+1$ 到 $r$), 如果小于, 那么当前的 $left$ 号会对 $right$ 到 $r$ 都有贡献,
 所以 $inc(sum,val[left])$。如果不是, 我们就直接计算 $1$ 到 $left-1$ 对 $right$ 的贡献, 就是 $inc(ans[id[right]],sum)$。
 
-上述的方法是要求左半边和右半边的右端点有序, 且左半边的最大时间小于等于右半边的最小时间的。我们可以采用先 $CDQ(l,mid)\ CDQ(mid+1,right)$ 的方法,**每一次算完当前的贡献, 就排好序**, 这样子就可以保证啦。既然是 $CDQ$, 那么可以直接归并排序, 常数小。
+上述的方法是要求左半边和右半边的右端点有序, 且左半边的最大时间小于等于右半边的最小时间的。我们可以采用先 $CDQ(l,mid)\ CDQ(mid+1,right)$ 的方法,**每一次算完当前的贡献, 就排好序**, 这样子就可以保证啦。既然是 CDQ , 那么可以直接归并排序, 常数小。
 
-然后解释一下为什么 $CDQ$ 要分治。对于一个点 $i$, 它经过 $\log\ n$ 层的分治以后, 必然会与每一个右区间算贡献。一开始右区间有 $\frac{n}{2}$ 个数字, 然后变为 $\frac{n}{4}\ \frac{n}{8}.etc$。时间复杂度涉及到递归, 这里作出大致的推测 : $\log\ n$ 层, 每一层的总和是 $n$, 那就是 $n \log\ n$。实际上应该是 $O(f(n) \log\ n)$, 我表示并不会主定理
+然后解释一下为什么 CDQ 要分治。对于一个点 $i$, 它经过 $\log\ n$ 层的分治以后, 必然会与每一个右区间算贡献。一开始右区间有 $\frac{n}{2}$ 个数字, 然后变为 $\frac{n}{4}\ \frac{n}{8}.etc$。时间复杂度涉及到递归, 这里作出大致的推测 : $\log\ n$ 层, 每一层的总和是 $n$, 那就是 $n \log\ n$。实际上应该是 $O(f(n) \log\ n)$
 
 最后注意一下时间相同, 先修改, 再查询 (虽然不知道为什么时间会相同)。
 
@@ -149,7 +149,7 @@ end;
 
 数据范围 : $N \leq 2 \times 10^6$。而树套树 (我指的是树状数组或者线段树) 怎么也只能 $N \leq 10^4$。
 
-这就展现了 $CDQ$ 比较好的以一面 **哪个修改会影响哪个查询**, 就不用考虑 $N$ 的大小, 不用考虑模拟矩阵。
+这就展现了 CDQ 比较好的以一面 **哪个修改会影响哪个查询**, 就不用考虑 $N$ 的大小, 不用考虑模拟矩阵。
 
 第一步, 我们把查询看做是一个二维前缀和的查询。也就是说, 我们对于 $x,y,x1,y1$ 的查询, 看做全部以 $1$ 开始的矩阵, 如下图 : (黑色的是加的, 红色的是减去的, 剩下的黄色就是目标矩阵)
 
@@ -195,10 +195,10 @@ begin
 end;
 ```
 
-最后总结 $CDQ$ 分治需要注意的地方:
+最后总结 CDQ 分治需要注意的地方:
 
-$I.\ CDQ$分治会按照各个参数的顺序而改变递归的顺序。
+1. CDQ 分治会按照各个参数的顺序而改变递归的顺序。
 
-$II.\ CDQ$分治的时间复杂度并不是非常的好, 常数巨大, 但是可以做那些二维以上的题目, 不用考虑 $N$ 的大小。 (但是询问太多还是会炸)
+2. CDQ 分治的时间复杂度并不是非常的好, 常数巨大, 但是可以做那些二维以上的题目, 不用考虑 $N$ 的大小。 (但是询问太多还是会炸)
 
-$III.\$有些人是直接 $Sort$ 的, 而不是归并排序, 所以 $CDQ$ 分治的三个步骤可以打乱。
+3. 有些人是直接 ```sort``` 的, 而不是归并排序, 所以 CDQ 分治的三个步骤可以打乱。(但是仍然要看清楚题目的要求)