<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
	<title>GZFLS Computer Science</title>
		<description>Computer Science club @ GZFLS，提供算法竞赛培训，机器人竞赛等，我们也会不定期更新论文精读和有趣的 Arduino Project</description>
		<link>https://gwcs.xyz</link>
		<atom:link href="https://gwcs.xyz/feed.xml" rel="self" type="application/rss+xml" />
		
		
			<item>
				<title>CS188 Chapter 14 Probabilistic Reasoning</title>
				<description>&lt;h2 id=&quot;141-representing-knowledge-in-an-uncertain-domain&quot;&gt;14.1 Representing Knowledge in an Uncertain Domain&lt;/h2&gt;

&lt;p&gt;This section will introduce a data structure called &lt;strong&gt;Bayesian network&lt;/strong&gt; to represent the dependencies between variables. Bayesian network can represent &lt;em&gt;any&lt;/em&gt; full-joint probability distribution and in many cases can do so very concisely.&lt;/p&gt;

&lt;p&gt;A Bayesian network is a directed acyclic graph (DAC) where each node is annotated with quantitative probability information.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Each node corresponds to a random variable, which may be discrete or continuous.&lt;/li&gt;
  &lt;li&gt;A set of directed links or arrows connects pairs of nodes. If there is an arrow from node $X$ to $Y$, $X$ is said to be a parent of $Y$.&lt;/li&gt;
  &lt;li&gt;Each node $X_i$ has a conditional probability distribution $\mathbf{P}(X_i\mid Parents(X_i))$ that quantifies the effect of the parents on the node.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210607204337.jpg&quot; alt=&quot;445d0b3c3422cc07a6e40f85fca27a8&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In each node of the Bayesian network, a conditional probability table (CPT) is stored. For instance, the node “$Toothache$” stores $\mathbf{P}(Toothache \mid Cavity)$.&lt;/p&gt;

&lt;p&gt;In general, a table for a Boolean variable with $k$ Boolean parents contains $2^k$ independently specifiable probabilities.&lt;/p&gt;

&lt;h2 id=&quot;142-the-semantics-of-bayesian-networks&quot;&gt;14.2 The Semantics of Bayesian Networks&lt;/h2&gt;

&lt;h3 id=&quot;1421-representing-the-full-joint-distribution&quot;&gt;14.2.1 Representing the full joint distribution&lt;/h3&gt;

&lt;p&gt;The full joint distribution of variables $X_1$ to $X_n$ can be represented in this way:&lt;/p&gt;

\[P(x_1, \cdots, x_n) = \prod_{i=1}^{n}{P(x_i \mid parents(X_i))}\]

&lt;p&gt;Where $parents(X_i)$ is the parent nodes of variable $X_i$.This equation defines what a given Bayesian network means.&lt;/p&gt;

&lt;h4 id=&quot;how-to-construct-bayesian-networks&quot;&gt;How to construct Bayesian Networks&lt;/h4&gt;

&lt;p&gt;Except the equation above, there is another way to calculate $P(x_1, \cdots, x_n)$. Using product rule, we can also represent it in this way:&lt;/p&gt;

\[P(x_1, \cdots, x_n) = P(x_n \mid x_{n-1}, x_{n-2}, \cdots, x_1)P(x_{n-1}, x_{n-2}, \cdots, x_1)\]

&lt;p&gt;Applying product rule recursively on the equation above, we can represent $P(x_1, \cdots, x_n)$ in a long product:&lt;/p&gt;

\[P(x_1, \cdots, x_n) = P(x_n \mid x_{n-1}, x_{n-2}, \cdots, x_1)P(x_{n-1} \mid  x_{n-2}, \cdots, x_1)\cdots P(x_2 \mid x_1)P(x_1) \\= \prod_{i=1}^{n}{P(x_i \mid x_{i-1} \cdots x_1)}\]

&lt;p&gt;Therefore, we can learn that[图片]&lt;/p&gt;

\[P(X_i\mid X_{i-1}. \cdots. X_i) = P(X_i \mid parents(X_i))\]

&lt;p&gt;This equation indicates that …
\(P(X\mid Parents(X))\;\bot\; P(Ancestor(X) \mid Parents(X))\)
&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210614220259.jpg&quot; alt=&quot;a48c4f85ffc63ba7ec657b08d301a7f&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;Nodes&lt;/em&gt;: First find a set of variables $X_1, \cdots, X_n$ that will be included into the Bayes Network. &lt;u&gt;The network will be more compact if the variables are ordered such that cause precede effect&lt;/u&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Links&lt;/em&gt; For $i = 1$ to $n$, do
    &lt;ul&gt;
      &lt;li&gt;Choose from $X_1, \cdots, X_{i-1}$ a minimal set of parents for $X_i$, such that Equation $P(X_i\mid X_{i-1}. \cdots. X_i) = P(X_i \mid parents(X_i))$ is satisfied.&lt;/li&gt;
      &lt;li&gt;For each parent insert a link from parent to $X_{i}$&lt;/li&gt;
      &lt;li&gt;Write down the conditional probability table, $\mathbf{P}(X_i \mid Parents(X_i))$&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;info&quot;&gt;
    The Bayesian network is a correct representation of the domain only if each node is conditionally independent of its other predecessors in the node ordering, given its parents.
&lt;/div&gt;
&lt;div class=&quot;notification&quot;&gt;
Some information is omitted here as they requires sophisticated knowledge in 2D Gaussian distribution, topology, etc. You can find them in Chapter 14.2 - 14.3
&lt;/div&gt;

&lt;h2 id=&quot;144-exact-inference-in-bayesian-networks&quot;&gt;14.4 Exact Inference in Bayesian Networks&lt;/h2&gt;

&lt;p&gt;The basic task for probabilistic inference system is to compute the posterior probability distribution for a set of &lt;strong&gt;query variables&lt;/strong&gt;, given some observed &lt;strong&gt;event&lt;/strong&gt; (the assignment of values to a set of &lt;strong&gt;evidence variables&lt;/strong&gt;).&lt;/p&gt;

\[\text{All Variables} = \text{Query Variables }\cup\text{ Evidence Variables }\cup\text{ Hidden Variables}\]

&lt;p&gt;A typical query asks for the posterior probability distribution $\mathbf{P}(X\mid \mathbf{e})$&lt;/p&gt;

&lt;h3 id=&quot;1441-inference-by-enumeration&quot;&gt;14.4.1 Inference by Enumeration&lt;/h3&gt;

&lt;p&gt;A query $\mathbf{P}(X \mid \mathbf{e})$ can be answered using the equation below:&lt;/p&gt;

\[\mathbf{P}(X \mid \mathbf{e}) = \alpha \mathbf{P}(X, \mathbf{e}) = \alpha \sum_y{\mathbf{P}(X,\mathbf{e}, \mathbf{y})}\]

&lt;p&gt;&lt;mark&gt;a query can be answered using a Bayesian Network by computing sums of products of conditional probablities from the network.&lt;/mark&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;

  &lt;p&gt;Suppose we have such a Bayesian Network&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210614221114.jpg&quot; alt=&quot;b1512cd7f41c44fc2aed0676e9f57cc&quot; style=&quot;zoom: 33%;&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;We use $B$ to represent the variable $Burglary$, $m$ and $j$ represent the known value of $JohnCalls$ and $MaryCalls$ (True or False). Now we want to calculate $\mathbf{P}(B\mid m, j)$&lt;/p&gt;

\[\begin{aligned}
	\mathbf{P}(B\mid m, j) &amp;amp;= \left\langle \frac{P(b, j, m)}{P(j, m)}, \frac{P(\neg b, j, m)}{P(j, m)} \right\rangle\\
	&amp;amp;= \alpha \left\langle \underbrace{P(b, j, m)}_{\text{Expand}}, P(\neg b, j, m)\right\rangle
\end{aligned}\]

  &lt;p&gt;Using &lt;strong&gt;Chain Rule&lt;/strong&gt;, we can expand $P(b, j, m, E, A)$&lt;/p&gt;

\[\begin{aligned}
P(b, j, m) &amp;amp;= \sum_E{\sum_A{P(b, j, m, E, A)}}\\
&amp;amp;= \sum_E{\sum_A{P(m \mid j, A, E, b)P(j \mid A, E, b)P(A \mid E, b)P(E\mid b)P(b)}}
\end{aligned}\]

  &lt;blockquote&gt;
    &lt;p&gt;Note: For simplicity&lt;/p&gt;

    &lt;p&gt;$x\bot y$ is the shorten for $P(x)\bot P(y)$&lt;/p&gt;

    &lt;p&gt;$x\bot y \mid a$ is the shorten for $P(x\mid a) \bot P(y\mid a)$&lt;/p&gt;

    &lt;p&gt;$x\bot y, z \mid a$ is the shorten for $P(x\mid a)\bot P(y\mid a)$ and $P(x\mid a)\bot P(z\mid a)$&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;p&gt;According to the structure of Bayesian Network, we can know that $m \bot j$,  $m \bot b, E \mid A$, $j \bot b, E \mid A$ and $b\mid E$. Therefore, we can simplify the formula above&lt;/p&gt;

\[\begin{aligned}
P(b, j, m) &amp;amp;= \sum_E{\sum_A{P(m \mid j, A, E, b)P(j \mid A, E, b)P(A \mid E, b)P(E\mid b)P(b)}}\\
&amp;amp;= \sum_E{\sum_A{P(m\mid A)P(j \mid A)P(A\mid E, b)P(E)P(b)}}
\end{aligned}\]

  &lt;p&gt;To simplify this formula, we can “extract the common factor” out from nested sum$\sum$.&lt;/p&gt;

\[\begin{aligned}
&amp;amp;P(b, j, m)\\
= &amp;amp;P(b)\sum_E\left({P(E)\sum_A\left({P(m \mid A)P(j\mid A)P(A\mid E, b)}\right)}\right)\\
= &amp;amp;P(b)\sum_E\left({P(E)\sum_A\left({\underbrace{P(m\mid Parents(m))P(j\mid Parents(j))P(A\mid Parents(A))}_{\text{Find these value in Bayesian Network}}}\right)}\right)
\end{aligned}\]
&lt;/blockquote&gt;

&lt;p&gt;The worst time complexity of query with enumeration is $O(n2^n)$&lt;/p&gt;

&lt;p&gt;To formally describe the process of Inference by Enumeration, we can use two functions - $\text{ENUMERATION-ASK}$  and $\text{ENUMERATE-ALL}$.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210615102519.jpg&quot; alt=&quot;e8e8e0482668ce9ff68fc7b628f4762&quot; style=&quot;zoom: 33%;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The $\times$ here represents the &lt;strong&gt;pointwise product&lt;/strong&gt; between vectors instead of scalar product.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here’s how to use $\text{ENUMERATION-ASK}$  and $\text{ENUMERATE-ALL}$ to evaluate $\text{ENUMERATION-ASK}(B, \lbrace j,m\rbrace, bn)$.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210615105150.jpg&quot; alt=&quot;8918902a08f4f456312d98b252d9846&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;notification&quot;&gt;
Some information is omitted here. You can find them in Chapter 14.4.2 - 14.4.4
&lt;/div&gt;

&lt;h2 id=&quot;145-approximate-inference-in-bayesian-networks&quot;&gt;14.5 Approximate Inference in Bayesian Networks&lt;/h2&gt;

&lt;p&gt;This section describes randomized sampling algorithms, also called &lt;strong&gt;Monte Carlo&lt;/strong&gt; algorithms, that provide approximate answers whose accuracy depends on the number of samples generated.&lt;/p&gt;

&lt;h3 id=&quot;1451-direct-sampling-methods&quot;&gt;14.5.1 Direct Sampling Methods&lt;/h3&gt;

&lt;h4 id=&quot;prior-sample&quot;&gt;Prior Sample&lt;/h4&gt;

&lt;p&gt;Step 1. Use topological sort to sort all variables in the Bayesian Network.&lt;/p&gt;

&lt;p&gt;Step 2. Assign a value to the first variable (the node with no Parents) randomly with probability distribution $\mathbf{P}(X_1)$.&lt;/p&gt;

&lt;p&gt;Step 3. Assign a value to next variable with probability distribution $\mathbf{P}(X_2 \mid Parents(X_2))$&lt;/p&gt;

&lt;p&gt;Step 4. Repeat Step 3 until all variables in Bayesian Network has an assignment&lt;/p&gt;

&lt;p&gt;After step 4, we successfully construct a sample from Bayesian network. By repeating the sampling for many times, we can approximate the Probability distribution $\mathbf{P}(X\mid e)$.&lt;/p&gt;

&lt;p&gt;Suppose $S_{PS}(x_1, \cdots, x_n)$ represents the probability of getting sample where $X_1 = x_1, \cdots, X_n=x_n$.&lt;/p&gt;

\[S_{PS}(x_1\cdots x_n) = \prod_{i=1}^n{P(x_i\mid Parents(X_i))}\]

&lt;p&gt;Suppose we have take $N$ direct samples and among them, there are $N_{PS}(x_1\cdots x_n)$ sample where $X_1=x_1\cdots X_n=x_n$. The ration between $N$ and $N_{SP}$ will converge as $N$ approach $\infty$.&lt;/p&gt;

\[\lim_{N\rightarrow\infty}{\frac{N_{PS}(x_1\cdots x_n)}{N}} = S_{PS}(x_1, \cdots, x_n)=P(x_1, \cdots, x_n)\]

&lt;p&gt;The estimated probability becomes exact in the large-sample limit. Such an estimate is called &lt;strong&gt;consistent&lt;/strong&gt;.&lt;/p&gt;

\[P(x_1, \cdots, x_m)\approx N_{PS}(x_1, \cdots, x_m)/N\]

&lt;h4 id=&quot;rejection-sampling&quot;&gt;Rejection Sampling&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Rejection sampling&lt;/strong&gt; is a general method for producing samples from a hard-to-sample distribution given an easy-to-sample distribution. It can produce a consistent estimation of the true probability.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210615134504.jpg&quot; alt=&quot;b00ce22da893459c32e8a44cc39f6e1&quot; style=&quot;zoom:50%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The biggest problem of rejection sampling is that it rejects too much samples! The number of samples being rejected increases exponentially as the number of evidence variable increases.&lt;/p&gt;

</description>
				<pubDate>Sun, 13 Jun 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/06/13/CS188-Chapter14.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/06/13/CS188-Chapter14.html</guid>
			</item>
		
			<item>
				<title>CS188 Ch13. Case Study - Recognize MNIST base on Naive Bayes</title>
				<description>&lt;h2 id=&quot;开始之前&quot;&gt;开始之前……&lt;/h2&gt;

&lt;p&gt;先下载 Case Study Package，其中包括了 Jupyter Notebook 文件，MNIST 数据集，和 Python 文件&lt;/p&gt;

&lt;div&gt;
&lt;button class=&quot;main-button&quot; onclick=&quot;window.location.href='https://pan.baidu.com/s/1p_530ZKFG8YbgFUdkehHDA'&quot;&gt;


&lt;img src=&quot;/assets/icon_db/python.svg&quot; style=&quot;display: inline-block; height: 2rem; width: 2rem; margin-bottom: -0.3rem;&quot; /&gt; Download the Case-Study Package
&lt;/button&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;提取码：gwcs&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;using-naive-bayes-network-to-recognize-mnist-handwriting-figures&quot;&gt;Using Naive Bayes’ Network to Recognize MNIST Handwriting Figures&lt;/h2&gt;

&lt;p&gt;This dataset contains two files - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mnist_test.csv&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mnist_train.csv&lt;/code&gt;. They are in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; directory. You can also download them from &lt;a href=&quot;https://www.kaggle.com/oddrationale/mnist-in-csv?select=mnist_train.csv&quot;&gt;this link&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;what-is-mnist&quot;&gt;What is MNIST?&lt;/h3&gt;

&lt;p&gt;MNIST is a set of hand-writing images collected by NIST. Each image is cropped to $28px \times 28px$. There exist a single digit in each image.&lt;/p&gt;

&lt;p&gt;The image is gray-scaled. Each pixel has a value in range $[0, 255]$. Where $0$ represents “white” and $255$ represents “black”.&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at MNIST first.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;load_csv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pathToCSV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    加载 csv 数据
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pathToCSV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;train_set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;load_csv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;./data/mnist_train.csv&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# 训练集，共 60,000 张（行）
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;load_csv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;./data/mnist_test.csv&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# 测试集，共 10,000 张（行）
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;display_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Display the image using ASCII char, also show the label on image
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Unable to display image other than size 28 * 28 and 1 label&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gray_chars&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; .:-=+*#%@&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gray_scale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Label: {}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixel&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]):&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gray_chars&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gray_scale&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Code:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;display_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Label: 0

                                                                   
                                                        
                              . + % + .                 
                            . % % % % %                 
                          . % % % % % % :               
                        : # % % % # : % % =             
                      + % % % % % % - * % +             
                    . % % % * = % % . : @ +             
                  . % % % *   : =       % % .           
                . + % % # :             % % +           
                * % % :                 % % *           
              : % % :                   % % *           
              * % *                     @ % *           
            : % % -                     % % +           
            - % %                     = % *             
            - % #                   = % # :             
            - % +               . + % *                 
            - % #             = % % +                   
            - % % + . . - * # % # + .                   
            - % % % % # % % % * =                       
              # % % % % % % +                           
                = % % % = .                             
                                                        

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;simplification-on-image-binarization&quot;&gt;Simplification on image: Binarization&lt;/h3&gt;

&lt;p&gt;To further simplify the model (and reduce the memory requirement of naive bayes classifier), we can &lt;strong&gt;binarize&lt;/strong&gt; the image.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210603162239.png&quot; alt=&quot;image-20210603162231955&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;binarize_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;120&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    [Label, Pixel 1, Pixel 2, ..., Pixel 784]
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;binaryImg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# include the label
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;binaryImg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixel&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]]&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# binarize image based on threshold
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binaryImg&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;display_binary_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;display_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;255&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixel&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]])&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;binary_train_set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;binarize_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;train_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;binary_test_set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;binarize_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Code:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;display_binary_image(binarize_image(train_set[5]))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Label: 2

                                                        
                                                        
                                    @                   
                            @ @ @ @ @ @                 
                        @ @ @ @ @ @ @ @                 
                    @ @ @ @ @ @     @ @                 
                    @ @ @ @ @       @ @                 
                  @ @ @ @ @         @ @                 
                    @               @ @                 
                                  @ @ @                 
                            @ @ @ @ @ @                 
                        @ @ @ @ @ @ @                   
                    @ @ @ @ @ @ @ @ @                   
                  @ @ @       @ @ @ @ @                 
              @ @ @ @       @ @ @ @ @ @ @ @             
            @ @ @         @ @ @         @ @ @ @ @       
            @ @       @ @ @ @               @ @         
          @ @ @ @ @ @ @ @ @                             
          @ @ @ @ @ @                                   
              @ @                                       
                                                        
                                                       
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;bayes-network-on-image-recognition&quot;&gt;Bayes Network on Image Recognition?&lt;/h3&gt;

&lt;p&gt;To begin with, we assume that the binary values on pixel are conditionally independent under the condition of &lt;strong&gt;label&lt;/strong&gt;.&lt;/p&gt;

\[\mathbf{P}(Pixel_1 \mid Label) \bot \mathbf{P}(Pixel_2 \mid Label) \bot ... \mathbf{P}(Pixel_{784} \mid Label)\]

&lt;p&gt;Since we know the input image, we know the value of each pixel, we can easily calculate $\mathbf{P}(pixel_1, pixel_2, \cdots ,pixel_{784} \mid Label)$ using this equation:&lt;/p&gt;

\[\mathbf{P}(pixel_1, pixel_2, \cdots, pixel_{784} \mid Label) = \prod_{i \in [1, 784]}{\mathbf{P}(pixel_i \mid Label)}\]

&lt;p&gt;For simplicity, use $X$ denotes for $\lbrace pixel_1, pixel_2, \cdots, pixel_{784} \rbrace$&lt;/p&gt;

\[\begin{aligned}
\mathbf{P}(Label \mid X) &amp;amp;= \alpha \mathbf{P}(X \mid Label)\mathbf{P}(Label)\\
    &amp;amp;= \alpha \langle P(X \mid label_0)P(label_0), P(X\mid label_1)P(label_1), \cdots, P(X\mid label_9)P(label_9)\rangle\\
    &amp;amp;= \alpha \langle \prod{P(pixel_i \mid label_0)\cdot P(label 0), \cdots}\rangle
\end{aligned}\]

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;LabelCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;                           &lt;span class=&quot;c1&quot;&gt;# Counter for Label, used to calculate P(Label)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PixelCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;784&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Counter for Pixel | Label, used to calculate P(pixel | label)
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binary_train_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LabelCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PixelCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# +1 if pixel is black, 0 otherwise
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;LabelDistribution&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LabelCountElem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;train_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LabelCountElem&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LabelCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;PixelDistribution&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LabelCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixel&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PixelCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Code:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Label Distribution:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LabelDistribution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Output ($\mathbf{P}(Label)$)：&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Label Distribution:
 [0.09871666666666666, 0.11236666666666667, 0.0993, 0.10218333333333333, 0.09736666666666667, 0.09035, 0.09863333333333334, 0.10441666666666667, 0.09751666666666667, 0.09915]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With the statistical data collected from the Training set, we can now construct our Naive Bayes classifier.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_pixel_prob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;global&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PixelDistribution&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;black_probability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PixelDistribution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;black_probability&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;black_probability&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;predict_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;global&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PixelDistribution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LabelDistribution&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;784&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;only predict image without label at 0&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pred_probability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pred_label&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;posterior_probability_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get_pixel_prob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pred_label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;posterior_probability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prob&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posterior_probability_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posterior_probability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prob&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# posterior_probability = \prod{P(pixel_i | label_pred)}
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;pred_probability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pred_label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;posterior_probability&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LabelDistribution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pred_label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pred_probability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prob&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prob&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pred_probability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;classification-on-test-set&quot;&gt;Classification on Test Set&lt;/h3&gt;

&lt;p&gt;Code:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;selected_image_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3101&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Predict Probability:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;predict_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;binary_test_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selected_image_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:])))&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;display_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;selected_image_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Output:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Predict Probability:
 [0.0, 0.0, 0.0, 1.3577222853703937e-55, 2.3620356632673247e-37, 1.0415370695140759e-36, 0.0, 0.9999999999999999, 6.262374232930145e-42, 1.1556946478312145e-16]
Label: 7

                                                        
                                                        
                                                        
                  + + - . : + + * % % % *               
                * % % % % % % % % % % % % =             
                # @ % % % % % % % % % % % % .           
              . % % % % % % % + - - * % % % .           
                # @ % % % +         = % % #             
                = % % % % :       . % % % =             
                . % % % +         + % % %               
                  : + = .       . % % % *               
                                # % % #                 
                              * % % % =                 
                            * % % % =                   
                          - % % % *                     
                        : % % % *                       
                        # % % * .                       
                    . * % % %                           
                    # % % % *                           
                  - % @ % #                             
                  * % % % #                             
                  % % @ % *                             
                  . * % +                               
                                                        
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
				<pubDate>Fri, 04 Jun 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/06/04/CS188-Naive-Bayes-MNIST.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/06/04/CS188-Naive-Bayes-MNIST.html</guid>
			</item>
		
			<item>
				<title>二维前缀和 2D Prefix Sum</title>
				<description>&lt;h3 id=&quot;前提条件&quot;&gt;前提条件&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
	&lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;数据结构：前缀和 Prefix Sum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;应用场景&quot;&gt;应用场景&lt;/h3&gt;

&lt;p&gt;在一些算法题中，我们需要快速求出二维数组内一个特定区域的所有值的和。这种时候，如果我们每次都使用遍历的方法求和，每次查询的时间复杂度是 $O(n^2)$，对于铜组以上的算法题来说这种时间复杂度一般是不可接受的。&lt;/p&gt;

&lt;p&gt;二维前缀和就是专门用于解决这个问题的一种数据结构。二位前缀和会在初始化的时候使用 $O(n^2)$ 的时间复杂度建立一张二维数组从当前位置到 $[0][0]$ 的所有数字的和的表格。当初始化完成后，每次 $query$ 操作只需要 $O(1)$ 的时间复杂度就可以完成。&lt;/p&gt;

&lt;div class=&quot;notification&quot;&gt;
    &lt;p&gt;
        注意这种数据结构并不适合在二维数组需要大量更新的情况下使用，因为二位前缀和数组每次更新需要重新构造从更新位置开始的所有表格。每次更改的时间复杂度是 $O(n^2)$
    &lt;/p&gt;
&lt;/div&gt;

&lt;h3 id=&quot;原理&quot;&gt;原理&lt;/h3&gt;

&lt;p&gt;二位前缀和数据结构会在内部维护两张表格 $T$ 和 $S$。$S[y][x]$ 处存储的值等于 $T$ 中所有 $(0, 0)$ 到 $(x, y)$ 的位置的值之和。&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210527100019.jpg&quot; alt=&quot;04eed1e3dc29fba7bb34be79cb605bb&quot; style=&quot;zoom:50%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当我们想查询两个点 $(x_1, y_1)$  与 $(x_2, y_2)$ 构成的矩形内部所有数字的和时，我们可以这样计算：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210527101837.jpg&quot; alt=&quot;84e8f29abc499e4d5bbd3e209144ab5&quot; style=&quot;zoom:50%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;表格 $S$ 可以使用下面这个公式遍历的方法生成&lt;/p&gt;

\[S[x][y] = S[x - 1][y] - S[x - 1][y - 1] + S[x][y - 1] + T[x][y]\]

&lt;blockquote&gt;
  &lt;p&gt;注意上面 $S$ 中内容的运算顺序，对于 Java 等数值类型有最大值的语言，这样的顺序可以一定程度上的避免出现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Overflow&lt;/code&gt; 问题&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;实现&quot;&gt;实现&lt;/h3&gt;

&lt;p&gt;下面是基于 Java &lt;a href=&quot;https://docs.oracle.com/javase/tutorial/java/generics/types.html&quot;&gt;范型 (Generic Type)&lt;/a&gt; 实现的一个二维数组。它可以存储任意数字类型的二维数组，但是查询时返回的内容总是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;double&lt;/code&gt; 类型。&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PrefixSum2D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[][]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[][]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}};&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;PrefixSum2D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PrefixSum2D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;query2DSum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valueTable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;();&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sumTable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;();&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;PrefixSum2D&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[][]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++){&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;());&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++){&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;initializeTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;constructTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;query2DSum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/*
            Query the sum of all numbers in range ([x1, x2], [y1, y2]) with Time Complexity O(1)
                (x1, y1) ------------- (x2, y1)
                    |                     |
                    |                     |
                (x1, y2) ------------- (x2, y2)
        */&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;slowUpdateTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/* Update 2D Prefix Sum Table with O(n^2) complexity */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;constructTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initializeTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/* Initialize the SumTable with size x * y and filled with null */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++){&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;());&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++){&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;constructTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;cm&quot;&gt;/*
        Construct Table from T[y][x]
        Time Complexity: O(n^2), slow, don't call this method frequently
         */&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++){&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++){&lt;/span&gt;
                &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;valueTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;doubleValue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;sumTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
	&lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=919&quot;&gt;USACO 2019 Silver Feb #2, Painting The Barn&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=1063&quot;&gt;USACO 2020 Silver Dec #2, Rectangular Pasture&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=923&quot;&gt;USACO 2019 Gold Feb #3, Painting The Barn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
				<pubDate>Wed, 26 May 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/05/26/2D-Prefix-Sum.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/05/26/2D-Prefix-Sum.html</guid>
			</item>
		
			<item>
				<title>线段树 Segment Tree</title>
				<description>&lt;h3 id=&quot;前提条件&quot;&gt;前提条件&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
	&lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;算法：递归 Recursion&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;数据结构：二叉树 Binary Tree&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;使用场景&quot;&gt;使用场景&lt;/h3&gt;

&lt;p&gt;线段树的应用场景与二进制索引树相似，当我们需要多次查询数组子区间的特性/数据并同时高效修改数组内容的时候，我们可以使用线段树。&lt;/p&gt;

&lt;p&gt;线段树并不是一种单一的数据结构 - 它代表了一类具有相同思想方法的数据结构 - 通过二叉树做到区间内容的高效查询，这里的内容可以是区间最大/最小值，区间和，等等 。&lt;/p&gt;

&lt;h3 id=&quot;数据结构&quot;&gt;数据结构&lt;/h3&gt;

&lt;p&gt;线段树是一个&lt;strong&gt;二叉树&lt;/strong&gt;，线段树中的每一个节点代表序列中的一个区间。假设对于 长度为 $N$ 的 array $A$，我们有对应的线段树 $T$，那么……&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$T$ 的根节点代表整个 array $A$&lt;/li&gt;
  &lt;li&gt;$T$ 的每个叶子节点都代表 array $A$ 中的一个值 $A[i]$，$0\leq i\lt N$&lt;/li&gt;
  &lt;li&gt;$T$ 中的每一个非叶节点都代表 array $A$ 的一个子序列 $A[i:j]$，$0\leq i\lt j \lt N$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210524105215.jpg&quot; alt=&quot;c8def3486964f5c15f15ac41ecacbc0&quot; style=&quot;zoom: 33%;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;在一个线段树中，所有的叶子节点&lt;strong&gt;一定&lt;/strong&gt;代表原数组中的一个值&lt;/p&gt;

  &lt;p&gt;注意线段树不一定是满二叉树&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;时间复杂度&quot;&gt;时间复杂度&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;初始化复杂度 - $O(n)$&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;对于一个长度为 $n$ 的 array，对应的线段树中最多一共有 $2n + 1$ 个节点。每个节点的初始化都是 $O(1)$ 的时间复杂度，所以线段树的初始化复杂度是 $O(n)$。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;更新复杂度 - $O(\log{n})$&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;对于一个长度为 $n$ 的 array，每次修改一个单一的值需要修改这个节点的所有父节点与“祖先节点”（例如父节点的父节点，父节点的父节点的父节点……）。对于一颗线段树，最多有 $\log_2{n}$ 的高度，所以更新一次线段树的值的时间复杂度是 $O(\log_2{n}) = O(\log{n})$&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;查询复杂度 - $O(\log{n})$&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;查询节点数量最多的情况出现于查询 $[l, l]$ 时，这时候我们需要从根节点一路递归的遍历到叶子节点，一共遍历 $O(\log{n})$ 个节点。所以查询区间的时间复杂度是 $O(\log{n})$&lt;/p&gt;

&lt;h3 id=&quot;java实现&quot;&gt;Java实现&lt;/h3&gt;

&lt;p&gt;一个线段树有三个主要的方法：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;初始化（Constructor）- 给定一个 Array，构建这个 Array 对应的线段树&lt;/li&gt;
  &lt;li&gt;查询 （Query）- 给定一个区间范围 $[l, r]$，返回这个区间的信息（最大值，最小值，和 etc）&lt;/li&gt;
  &lt;li&gt;更新 （Update）- 给定 index $i$ 与新的值 $v$，更新线段树&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;下面，我们会实现一个基于 &lt;a href=&quot;https://docs.oracle.com/javase/tutorial/java/generics/types.html&quot;&gt;范型 (Generic Type)&lt;/a&gt; 的最小线段树。对于任意实现了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Comparable&lt;/code&gt; 接口的类型 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayList&amp;lt;T&amp;gt;&lt;/code&gt;，我们都可以使用这个线段树来求出区间 $[l, r]$ 中的最小对象 $T$。&lt;/p&gt;

&lt;h4 id=&quot;helper-functions&quot;&gt;Helper Functions&lt;/h4&gt;

&lt;p&gt;在正式实现线段树前，我们先写一些后面可以用到的 Helper Functions。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;genericMin&lt;/code&gt; 函数通过比对 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T.compareTo&lt;/code&gt; 的值来返回两个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; 对象中较小的一个对象&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getLChild&lt;/code&gt; 计算出当前节点的左子节点的 index&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRChild&lt;/code&gt; 计算出当前节点的右子节点的 index&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inInterval&lt;/code&gt; 计算出区间 $[l1, r1]$ 和 $[l2, r2]$ 之间的关系&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SegmentTree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Comparable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    
	&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getLChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getRChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;genericMin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;compareTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;inInterval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Intervals do not have any intersection&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Interval 2 complete in Interval 1&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;                           &lt;span class=&quot;c1&quot;&gt;// Interval 2 partially intersect with Interval 1&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;注意我们的 tree 属性使用的是 ArrayList 而不是 array&lt;/p&gt;

  &lt;p&gt;这是因为 Java 中不能创造 Generic Type Array&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;construct-segment-tree&quot;&gt;Construct Segment Tree&lt;/h4&gt;

&lt;p&gt;我们使用递归的方法来构建线段树 - 根节点的范围是 $[0, arr.length - 1]$，计算出中间的节点 $mid = (arr.length - 1) / 2$，左节点的范围就是 $[0, mid]$，右节点的范围是 $[mid + 1, arr.length - 1]$。&lt;/p&gt;

&lt;p&gt;当节点的范围是 $[l, r]$ 且 $l = r$ 时，节点的值就是 Array 中对应元素的值 - 此时这个节点时叶子节点。&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SegmentTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Collections&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nCopies&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;constructTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;constructTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;constructTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getLChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;constructTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;genericMin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getLChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;update-segment-tree&quot;&gt;Update Segment Tree&lt;/h4&gt;

&lt;p&gt;类似的，我们在更新 Segment Tree 时也使用递归的方法更新 - 如果要修改的 index 在当前节点的范围内，我们就递归的修改下一层，最后再 bottom-up 的更新整条路径上的 $O(\log{n})$ 个节点&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updateTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;updateTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updateTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;updateTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getLChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;updateTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;genericMin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getLChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;query-interval-minimum&quot;&gt;Query Interval Minimum&lt;/h4&gt;

&lt;p&gt;在查询线段树中的区间最小值时，我们把所有情况分为三种：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;当前节点代表的区间完全在查询的区间内&lt;/li&gt;
  &lt;li&gt;当前节点代表的区间部分在查询的区间内&lt;/li&gt;
  &lt;li&gt;当前节点代表的区间完全不在查询的范围内&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;对这三种情况，我们采取不同的动作&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;情况&lt;/th&gt;
      &lt;th&gt;操作&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;节点区间完全在查询区间内&lt;/td&gt;
      &lt;td&gt;返回当前节点的值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;节点区间部分在查询区间内&lt;/td&gt;
      &lt;td&gt;继续向下递归，返回左节点与右节点返回值的较小值&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;节点区间完全不在查询区间内&lt;/td&gt;
      &lt;td&gt;返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;queryMin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;queryMin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;queryMin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;inInterval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;inInterval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftInterval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;queryMin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getLChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightInterval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;queryMin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getRChild&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mid&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftInterval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightInterval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rightInterval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leftInterval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;genericMin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;leftInterval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rightInterval&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;对于基于数组&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;的线段树，我们执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queryMin(2, 3)&lt;/code&gt; 时函数的递归情况如下&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210524115756.jpg&quot; alt=&quot;fb5b1012c2c20d4f2ab433ad800d475&quot; style=&quot;zoom:33%;&quot; /&gt;&lt;/p&gt;

&lt;details&gt;
&lt;summary&gt;&lt;h3&gt;Click to see Java Full Code&lt;/h3&gt;&lt;/summary&gt;
    &lt;pre&gt;
        &lt;code class=&quot;java&quot;&gt;
 /* Segment Tree, Java */

import java.util.*;

public class SegmentTree &amp;lt;T extends Comparable&amp;lt;T&amp;gt;&amp;gt;{

    public static void main(String[] args) {
        SegmentTree&amp;lt;Integer&amp;gt; test = new SegmentTree&amp;lt;&amp;gt;(new Integer[]{1, 2, 3, 4, 5, 6});
        System.out.println(test.dumpTree());
        // test.updateTree(0, 7);
        // System.out.println(test.dumpTree());
        System.out.println(test.queryMin(2, 5));
    }
    
    private ArrayList&amp;lt;T&amp;gt; tree;
    private T[] value;
    
    public SegmentTree(T[] values){
        this.tree = new ArrayList&amp;lt;&amp;gt;(Collections.nCopies(values.length * 2 + 1, null));
        this.value = values;
        this.constructTree(0, 0, values.length - 1);
    }
    
    public void updateTree(int index, T val){
        this.updateTree(0, 0, this.value.length - 1, index, val);
    }
    
    public T queryMin(int l, int r){
        return queryMin(0, 0, this.value.length - 1, l, r);
    }
    
    public ArrayList&amp;lt;T&amp;gt; dumpTree(){
        return this.tree;
    }
    
    private T queryMin(int node, int start, int end, int l, int r){
        if (this.inInterval(l, r, start, end) == 0){ return null; }
        else if (this.inInterval(l, r, start, end) == 1){ return this.tree.get(node); }
        int mid = (start + end) / 2;
        T leftInterval = this.queryMin(this.getLChild(node), start, mid, l, r);
        T rightInterval = this.queryMin(this.getRChild(node), mid + 1, end, l, r);
        if (leftInterval == null){ return rightInterval; }
        else if (rightInterval == null){ return leftInterval; }
        else{ return this.genericMin(leftInterval, rightInterval); }
    }
    
    private void updateTree(int node, int l, int r, int index, T val){
        if (l == r){
            this.tree.set(node, val);
            this.value[l] = val;
        }
        else{
            int mid = (l + r) / 2;
            if (l &amp;lt;= index &amp;amp;&amp;amp; index &amp;lt;= mid){ this.updateTree(this.getLChild(node), l, mid, index, val); }
            else{ this.updateTree(this.getRChild(node), mid + 1, r, index, val); }
            this.tree.set(node, this.genericMin(this.tree.get(this.getLChild(node)), this.tree.get(this.getRChild(node))));
        }
    }
    
    private void constructTree(int node, int l, int r) {
        if (l == r) {
            tree.set(node, value[l]);
        } else {
            int mid = (l + r) / 2;
            this.constructTree(this.getLChild(node), l, mid);
            this.constructTree(this.getRChild(node), mid + 1, r);
            tree.set(node, this.genericMin(tree.get(this.getLChild(node)), tree.get(this.getRChild(node))));
        }
    }
    
    private int getLChild(int index){ return index * 2 + 1; }
    private int getRChild(int index){ return index * 2 + 2; }
    private T genericMin(T o1, T o2){
        if (o1.compareTo(o2) &amp;gt; 0){ return o2; }
        return o1;
    }
    private int inInterval(int l1, int r1, int l2, int r2){
        if (r2 &amp;lt; l1 || l2 &amp;gt; r1){ return 0; }        // Intervals do not have any intersection
        else if (l2 &amp;gt;= l1 &amp;amp;&amp;amp; r2 &amp;lt;= r1){ return 1; } // Interval 2 complete in Interval 1
        else{ return 2; }                           // Interval 2 partially intersect with Interval 1
    }
}
        &lt;/code&gt;
    &lt;/pre&gt;
&lt;/details&gt;

&lt;h3 id=&quot;问题练习&quot;&gt;问题练习&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
	&lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/range-sum-query-mutable/&quot;&gt;Leetcode 307. Range Sum Query - Mutable&lt;/a&gt; 非常 straight-forward 的 Segment Tree 问题&lt;/li&gt;
	&lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/the-skyline-problem/&quot;&gt;Leetcode 218. The Skyline Problem&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/count-of-smaller-numbers-after-self/&quot;&gt;Leetcode 318. Count of Small Numbers After Self&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=1041&quot;&gt;USACO 2020 US Open Contest, Gold Problem 1. Haircut&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=693&quot;&gt;USACO 2017 January Contest, Gold Problem 1. Balanced Photo&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=719&quot;&gt;USACO 2017 February Contest, Gold Problem 3. Why Did the Cow Cross the Road III&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;
</description>
				<pubDate>Fri, 21 May 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/05/21/Segment-Tree.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/05/21/Segment-Tree.html</guid>
			</item>
		
			<item>
				<title>CS188 Chapter 6 Constraint Satisfaction Problems</title>
				<description>&lt;h2 id=&quot;61-define-constraint-satisfaction-problems&quot;&gt;6.1 Define Constraint Satisfaction Problems&lt;/h2&gt;

&lt;p&gt;A CSP contains three components - $X$, $D$ and $C$.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$X$ is a set of variables&lt;/li&gt;
  &lt;li&gt;$D$ is a set of domains, one for each variable.&lt;/li&gt;
  &lt;li&gt;$C$ is a set of constraints that specify the allowable combination between variables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each constraint can be represent in two parameters - the $scope$ and the $relation$. The $scope$ define the variables that is related with this constraint. The $relation$ define the values that variables can take.&lt;/p&gt;

&lt;p&gt;The $relation$ can be either an explicit list of all legal value tuple the variables can get or an abstract relation.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Example 1 (Abstract, Implicit Relation) : If the constraint is $x &amp;lt; y$. The formal way to represent constraint will be:&lt;/p&gt;

\[\langle scope:(x, y),\quad relation:\;\lt\rangle\]

  &lt;p&gt;Example 2 (Explicit Relation): If we have $0 &amp;lt; x &amp;lt; 4$ and $0 &amp;lt; y &amp;lt; 3$, the constraint can be represented in this way:&lt;/p&gt;

\[\langle
	scope: (x, y),\quad
	relation: [(1, 1), (1, 2), \cdots, (3, 1), (3, 2)]
\rangle\]
&lt;/blockquote&gt;

&lt;p&gt;To solve the Constraint Satisfaction Problem (abbr. as CSP below), we need to define the solution and state space for CSP first. Each state of CSP is defined by an &lt;u&gt;**assignment** of values to some or all of the variables&lt;/u&gt;.&lt;/p&gt;

&lt;p&gt;An assignment that does NOT violate any constraint in $C$ is called a &lt;strong&gt;consistent assignment&lt;/strong&gt; (or, &lt;strong&gt;legal assignment&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Complete Assignment&lt;/strong&gt; is an assignment where every variable in $X$ is assigned.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Solution&lt;/strong&gt; of CSP is both Complete Assignment and Consistent Assignment.&lt;/p&gt;

&lt;h2 id=&quot;62-why-we-need-csp&quot;&gt;6.2 Why we need CSP&lt;/h2&gt;

&lt;p&gt;In the real world, many problems can be converted to CSP. As long as we have a legal CSP solver, we can generalize this solver to different problems with little difficulty. It will be easier to use a generalized CSP solver than design a custom solution using domain-specific knowledge.&lt;/p&gt;

&lt;h2 id=&quot;63-solving-csp&quot;&gt;6.3 Solving CSP&lt;/h2&gt;

&lt;p&gt;When we are finding the solution of CSP, once we find out that a partial assignment is not a solution, we can immediately discard further refinements of the partial assignment.&lt;/p&gt;

&lt;h3 id=&quot;631-types-of-constraints-in-csp&quot;&gt;6.3.1 Types of Constraints in CSP&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Constraint Type&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Unary Constraint&lt;/td&gt;
      &lt;td&gt;Constraint that only contain one variable in the scope&lt;br /&gt;Example: $\langle (x), x\neq 2\rangle$&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Binary Constraint&lt;/td&gt;
      &lt;td&gt;Constraint that contains two variables in the scope&lt;br /&gt;Example: $\langle (x, y), x &amp;lt; y \rangle$&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;k-ary Constraint&lt;/td&gt;
      &lt;td&gt;Constraint that contains $k$ variables in the scope&lt;br /&gt;Example: $\langle (x, y, z), \max(x, y, z) &amp;lt; 5 \rangle$&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Global Constraint&lt;/td&gt;
      &lt;td&gt;Constraint that involving all variables in $X$&lt;br /&gt;Example: $Alldiff$ Constraint requires all variables in $X$ has different assigned value.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;mark&gt;Every finite-domain constraint can be converted to a set of binary constraints if enough auxiliary variables are introduced.&lt;/mark&gt; Therefore, we can &lt;mark&gt;Transform every CSP into CSP with binary constraint only&lt;/mark&gt;.&lt;/p&gt;

&lt;h3 id=&quot;632-constraint-propagation-inference-in-csp&quot;&gt;6.3.2 Constraint Propagation: Inference in CSP&lt;/h3&gt;

&lt;p&gt;A regular search algorithm can only do one thing: search. In CSP, the algorithm can search or do specific type of &lt;strong&gt;inference&lt;/strong&gt; called &lt;strong&gt;constraint propagation in CSP&lt;/strong&gt;. Using constraint to reduce the number of legal values of a variable, which, in turn reduce the legal values of another variable.&lt;/p&gt;

&lt;p&gt;Constraint propagation can work during the search process or work as a pre-processing step.&lt;/p&gt;

&lt;p&gt;The key idea of constraint propagation is the &lt;strong&gt;local consistency&lt;/strong&gt;. If we see each variable in CSP as node, binary constraint as edge of graph, the local consistency is the consistency in a part of the whole constraint graph.&lt;/p&gt;

&lt;div class=&quot;info&quot;&gt;&lt;p&gt;Basically, you can see local consistency as a set of pruning algorithms running on CSP. By cutting off domain of each variable, the workload for search algorithm is greatly reduced.&lt;/p&gt;&lt;/div&gt;

&lt;h4 id=&quot;node-consistency&quot;&gt;Node Consistency&lt;/h4&gt;

&lt;blockquote&gt;
  &lt;p&gt;Node Consistency Check tighten the unary domain using unary constraint&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A single variable is &lt;strong&gt;node-consistent&lt;/strong&gt; if all the values in the variable’s domain satisfy the variable’s unary constraints.&lt;/p&gt;

&lt;p&gt;It is always possible to eliminate all the unary constraints in a CSP by running node consistency.&lt;/p&gt;

&lt;h4 id=&quot;arc-consistency&quot;&gt;Arc Consistency&lt;/h4&gt;

&lt;blockquote&gt;
  &lt;p&gt;Arc Consistency Check tighten the unary domain using binary constraint&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A variable in a CSP is &lt;strong&gt;arc-consistent&lt;/strong&gt; if every value in its domain satisfies the variable’s binary constraints.&lt;/p&gt;

&lt;p&gt;Formally speaking, $X_i$ is arc-consistent with respect to $X_j$ if for every value in $D_i$ there exist some value in $D_j$ such that the binary constraint between $X_i$ and $X_j$ is satisfied.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210529155034.jpg&quot; alt=&quot;2787acae2d13b8f1188d0dd505ec2ec&quot; style=&quot;zoom: 25%;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note - &lt;em&gt;iff&lt;/em&gt; stands for &lt;em&gt;if and only if&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AC3 is the most popular algorithm for arc consistency. To make every variable arc-consistent, the AC-3 algorithm maintains a queue of arcs to consider. Initially, the queue contains all the arcs in the CSP. AC-3 then pops off an arbitrary arc $(X_i, X_j)$ from the queue and makes $X_i$ arc-consistent with respect to $X_j$.&lt;/p&gt;

&lt;p&gt;If this step makes the domain $D_i$ of variable $X_i$ unchanged, we will move forward to next arc.&lt;/p&gt;

&lt;p&gt;If not, we add to the queue all arcs $(X_k, X_i)$ where $X_k$ is a neighbor of $X_i$. This is because the change of domain $D_i$ may lead to further reduction in the domain of $D_k$, even if we have previously considered $X_k$.&lt;/p&gt;

&lt;p&gt;&lt;button class=&quot;main-button&quot; onclick=&quot;window.location.href='https://markchenyutian.github.io/blog/artificial intelligence/2020/10/09/Constraint-Satisfaction-Problem.html'&quot;&gt;More about Arc Consistency Algorithm&lt;/button&gt;&lt;/p&gt;

&lt;p&gt;An arc-consistency CSP is &lt;strong&gt;equivalent&lt;/strong&gt; to original CSP, but faster to search because its variables has smaller domains.&lt;/p&gt;

&lt;h4 id=&quot;path-consistency&quot;&gt;Path Consistency&lt;/h4&gt;

&lt;blockquote&gt;
  &lt;p&gt;Path Consistency Check tighten the binary constraints by using implicit constraints that are inferred by triples of variables&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Arc Consistency, we are using binary constraint to optimize the unary domain. For most of the cases, this works well and can directly find solution (every domain is restricted to only 1 value) or prove that there is no solution for CSP (at least one domain contains 0 valid value).&lt;/p&gt;

&lt;p&gt;However, in some situation, the arc consistency has nothing to do with the unary domain using only binary constraint.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Example 3. A situation that arc consistency doesn’t work as expected&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210529224801.jpg&quot; alt=&quot;f4a3bf197f46b09d5beb4c4abe7ccf2&quot; style=&quot;zoom:33%;&quot; /&gt;&lt;/p&gt;

  &lt;p&gt;$X = {x, y, z}$&lt;/p&gt;

  &lt;p&gt;$D = {[Red, Blue], [Red, Blue], [Red, Blue]}$&lt;/p&gt;

  &lt;p&gt;$C = {\langle(x, y), x\neq y\rangle, \langle(z, y), z\neq y\rangle, \langle(x, z), x\neq z\rangle}$&lt;/p&gt;

  &lt;p&gt;If we are running arc consistency on this CSP, no domain will be changed. (When $x = Red$, $y = Blue$ is valid and vice versa). However, it is clear that this CSP will have no solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To solve this problem, we introduce the thought of Path Consistency.&lt;/p&gt;

&lt;p&gt;Formal description of Path Consistency:&lt;/p&gt;

&lt;p&gt;A two-variable set ${x_i, x_j}$ is path consistent with a third-variable ${x_k}$ if for every assignment ${x_i = a, x_j=b}$ that satisfy the constraint between $x_i$ and $x_j$, there exists a valid assignment to $x_k$ such that the constraint between $x_k$ and $x_i$, $x_k$ and $x_j$ is not violated.&lt;/p&gt;

&lt;h4 id=&quot;k-consistency&quot;&gt;$k$-Consistency&lt;/h4&gt;

&lt;p&gt;A generalized way to represent consistency of CSP is called $k$-consistency. A CSP is $k$-consistent if for any set of $k-1$ variables and for any consistent assignment to these variables, there always exist a consistent assignment to $k$th variable.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Node Consistency = 1-consistency, Arc Consistency = 2-consistency, Path Consistency = 3-consistency&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A CSP is &lt;strong&gt;strongly  k-consistent&lt;/strong&gt; if it is $k$-consistent and is also $(k-1)$-consistent, $(k-2)$-consistent … all the way to $1$-consistent.&lt;/p&gt;
</description>
				<pubDate>Tue, 11 May 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/05/11/CS188-Chapter6.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/05/11/CS188-Chapter6.html</guid>
			</item>
		
			<item>
				<title>队列 Queue</title>
				<description>&lt;h3 id=&quot;前置条件&quot;&gt;前置条件&lt;/h3&gt;

&lt;p&gt;在学习这个知识点前，你应该先学习……&lt;/p&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
	&lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/03/02/Time-Complexity.html&quot;&gt;理论基础：时间复杂度 Time Complexity&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;数据结构：链表 Linked List&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;队列&quot;&gt;队列&lt;/h3&gt;

&lt;p&gt;队列 (Queue) 是一种用于收集数据的线性数据结构，主要有两个操作：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;放入 (Push): 将元素放入队列中&lt;/li&gt;
  &lt;li&gt;取出 (Pop) : 将&lt;strong&gt;最先放入的元素&lt;/strong&gt;从队列中取出&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;因为在这个数据结构中，最先放入的元素会被最先取出来，和日常生活中的排队情境一样，所以这个数据结构被称作&lt;strong&gt;队列&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://markdown-img-1304853431.cos.ap-guangzhou.myqcloud.com/20210510105154.png&quot; alt=&quot;Fifo_queue&quot; style=&quot;zoom:67%;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;编程实现&quot;&gt;编程实现&lt;/h3&gt;

&lt;h4 id=&quot;0---一个基于-list-的朴素实现&quot;&gt;0 - 一个基于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list&lt;/code&gt; 的朴素实现&lt;/h4&gt;

&lt;p&gt;在 Python 与 Java 中，语言的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list&lt;/code&gt; 都提供了删除特定元素和在列表末尾添加元素的方法。 所以一种最朴素的实现可以直接使用语言的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list&lt;/code&gt; 来完成。&lt;/p&gt;

&lt;pre&gt;
	&lt;code class=&quot;python&quot;&gt;
class Queue:
	def __init__(self):
		self.data = list()

	def push(self, element):
		self.data.append(element)
	
	def pop(self):
		if len(self.data) &amp;gt; 0: return self.data.pop(0)
		else: raise Exception(&quot;Cannot pop from an Empty Queue&quot;)
	
	&lt;/code&gt;
	&lt;code class=&quot;java&quot;&gt;
import java.util.*;

class Queue{
	private ArrayList&amp;lt;Integer&amp;gt; arr = new ArrayList&amp;lt;&amp;gt;();

	public void push(int element){
		this.arr.add(element);
	}
	
	public int pop(){
		if (this.arr.size() &amp;gt; 0){
			int result = this.arr.get(0);
			this.arr.remove(0);
			return result;
		}
		else{
			return -1;
		}
	}
}
	&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;这种实现方法虽然可以 work，但是当你考虑时间复杂度的时候，你会发现这个实现实际上是非常低效的 - 每次从队列中取出一个元素的时候，你都要从队列中拿出第 0 项，同时将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 ~ n&lt;/code&gt; 的所有元素依次向前挪动一格。 这说明每次从队列中取出元素的时间复杂度是 $O(n)$。&lt;/p&gt;

&lt;p&gt;那么有没有可能换一种实现数据结构的方法，从而达到放取都是 $O(1)$ 的时间复杂度的效果呢？&lt;/p&gt;

&lt;p&gt;下面我们来看看如何使用刚刚学习的 &lt;strong&gt;链表&lt;/strong&gt; 数据结构来提高 Queue 的效率&lt;/p&gt;

&lt;h4 id=&quot;1---更加高效的队列链表&quot;&gt;1 - 更加高效的队列（链表）&lt;/h4&gt;

&lt;p&gt;虽然访问链表中间的第 $n$ 个元素需要 $O(n)$ 的时间复杂度，我们可以非常方便的在链表的首尾做对元素进行增删的操作。每次在链表末尾增添一个元素只需要 $O(1)$ 的时间复杂度；同时，删除链表头部的元素也只需要 $O(1)$ 的时间复杂度。通过这两个特性，我们可以让队列做到进出都只需要 $O(1)$ 的时间复杂度。&lt;/p&gt;

&lt;pre&gt;
	&lt;code class=&quot;python&quot;&gt;
class LinkedListNode:
    def __init__(self, val: int) -&amp;gt; None:
        self.next = None
        self.val = val

class Queue:
    def __init__(self) -&amp;gt; None:
        self.head = None
        self.tail = None
        self.size = 0
    
    def push(self, val: int) -&amp;gt; None:
        self.size += 1
        new_node = LinkedListNode(val)
        if self.head == None:
            self.head = new_node
            self.tail = new_node
        else:
            self.tail.next = new_node
            self.tail = self.tail.next
    
    def pop(self) -&amp;gt; int:
        self.size -= 1
        val = self.head.val
        self.head = self.head.next
        return val
    
    def size(self) -&amp;gt; int:
        return self.size
    
    def peek(self) -&amp;gt; int:
        return self.head.val
    
    def __str__(self) -&amp;gt; str:
        ptr = self.head
        string = &quot;HEAD -&amp;gt; &quot;
        while ptr.next != None:
            string += str(ptr.val) + &quot; -&amp;gt; &quot;
            ptr = ptr.next
        string += str(ptr.val) + &quot; -&amp;gt; &quot;
        string += &quot;TAIL&quot;
        return string
    &lt;/code&gt;
    &lt;code class=&quot;java&quot;&gt;
Not Implemented yet, see Python Version
	&lt;/code&gt;
&lt;/pre&gt;

&lt;h4 id=&quot;2---更加高效的队列循环数组&quot;&gt;2 - 更加高效的队列（循环数组）&lt;/h4&gt;

&lt;p&gt;除了链表以外，我们还可以用循环数组来实现队列。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://markdown-img-1304853431.cosgz.myqcloud.com/20210730170748.jpg&quot; alt=&quot;b0da01935156ce1789cbf366607545d&quot; /&gt;&lt;/p&gt;

&lt;pre&gt;
	&lt;code class=&quot;python&quot;&gt;
class Queue:
    def __init__(self, max_capacity: int) -&amp;gt; None:
        self.arr = [0] * max_capacity
        self.max_len = max_capacity
        self.start = 0
        self.end = 0
    
    def size(self) -&amp;gt; int:
        return self.end - self.start
    
    def push(self, item: int) -&amp;gt; None:
        self.end += 1
        actual_index = (self.end - 1) % self.max_len
        self.arr[actual_index] = item
    
    def pop(self) -&amp;gt; None:
        actual_index = self.start % self.max_len
        self.start += 1
        return self.arr[actual_index]
    
    def peek(self) -&amp;gt; int:
        return self.arr[self.start % self.max_len]
    
    def __str__(self) -&amp;gt; str:
        string = &quot;[ &quot;
        for index, num in enumerate(self.arr):
            string += str(num)
            if index == self.start % self.max_len:
                string += &quot;(START)&quot;
            if index == self.end % self.max_len:
                string += &quot;(END)&quot;
            string += &quot; | &quot;
        string += &quot; ]&quot;
        return string
	&lt;/code&gt;
	&lt;code class=&quot;java&quot;&gt;
Not Implemented Yet, see Python Version
	&lt;/code&gt;
&lt;/pre&gt;

&lt;h3 id=&quot;练习&quot;&gt;练习&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
	&lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://vjudge.net/problem/CodeForces-545D&quot;&gt;Code Forces 545-D | Queue&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://vjudge.net/problem/HackerRank-ctci-queue-using-two-stacks&quot;&gt;HackerRank | A tale of two Stacks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
				<pubDate>Mon, 10 May 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/05/10/Queue.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/05/10/Queue.html</guid>
			</item>
		
			<item>
				<title>Binary Index Tree (Fenwick Tree) 二叉索引树</title>
				<description>&lt;h3 id=&quot;前置技能&quot;&gt;前置技能&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/03/02/Time-Complexity.html&quot;&gt;理论基础：时间复杂度 Time Complexity&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;算法：递归 Recursion&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;数据结构：二叉树 Binary Tree&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;数据结构：前缀和 Prefix Sum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;Python Version not Implemented Yet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;traditional-approach-1&quot;&gt;Traditional Approach 1&lt;/h3&gt;

&lt;p&gt;在实际生活中，我们常常需要计算一个给定&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array&lt;/code&gt; 特定范围内所有数的和。如果只有这一个需求的话，我们可以很方便的构建出一个静态的数组来达到$O(1)$的时间复杂度。在这样的一个数组中，每一个位置上的数符合：&lt;/p&gt;

\[\text{arr}[n] = \text{arr}[n - 1] + x[n]\]

\[\text{arr}[0] = x[0]\]

&lt;p&gt;这样，当我们需要计算数列&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt;到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt;的数字的和时，我们只用计算 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arr[n] - arr[m]&lt;/code&gt;就可以了。&lt;/p&gt;

&lt;p&gt;然而，与计算的超高性能相比，这种方法要求我们操作的数列&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;是基本保持不变的，一旦&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;中的某一个值发生了变化，我们就要更新一次整个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arr&lt;/code&gt;数组，这直接导致了修改的$O(n)$复杂度。&lt;/p&gt;

&lt;h3 id=&quot;traditional-approach-2&quot;&gt;Traditional Approach 2&lt;/h3&gt;

&lt;p&gt;如果我们想要我们的数据结构可以接受大量的修改，我们也可以使用一个更加朴素的方法 - 我们只存储数列&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;，每次要计算区间和时，我们就遍历一次整个区间从而计算区间内所有元素的和。&lt;/p&gt;

&lt;p&gt;使用这种朴素的方法，虽然计算区间和的复杂度位$O(n)$，每次我们对数组&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;进行修改却不需要额外的操作，只有$O(1)$的复杂度。&lt;/p&gt;

&lt;h3 id=&quot;why-traditional-approach-fail&quot;&gt;Why Traditional Approach Fail&lt;/h3&gt;

&lt;p&gt;我们知道，一个算法的时间复杂度是由算法中最耗时间的步骤所决定的，也就是说，如果我们在一个循环中同时需要查询数组&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;的区间和并且修改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;，那么整个循环内的时间复杂度会由其中最耗时间的步骤决定 - $O(n)$。&lt;/p&gt;

&lt;p&gt;二进制索引树被设计出来处理这种情况，它很好的在两种传统方法间做出取舍，使得我们可以同时以$O(\log{n})$的时间复杂度进行数组的修改和区间和查询操作。&lt;/p&gt;

&lt;h2 id=&quot;data-structure---bit&quot;&gt;Data Structure - BIT&lt;/h2&gt;

&lt;p&gt;虽然BIT的名字是“二叉索引树”，实际上在程序中，我们并没有使用一个“树”的结构去存储BIT对象，而是将其放在一个数组中，这种结构被称为“树状数组”，许多树结构也使用了这样的形式 - 例如二叉堆模型。&lt;/p&gt;

&lt;p&gt;这是一个BIT数据结构的内部属性：&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BinaryIndexTree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
    
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;BIT之所以中间有一个“index”，是因为BIT的构造和操作过程中都要使用索引的一个属性 - 索引( + 1后)二进制中最后一个1的位置。&lt;/p&gt;

&lt;h3 id=&quot;helper-function---least-significant-one&quot;&gt;Helper Function - Least Significant One&lt;/h3&gt;

&lt;p&gt;在 Java 中，我们可以写一个这样的函数来找到整数二进制最后一位的1在哪里：&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findLastBinaryOne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binaryIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toBinaryString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binaryIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;--){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;binaryIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)){&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binaryIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通过计算索引 + 1后的二进制的最后一位1在哪里，我们可以得到BIT中这个位置的节点在树中的高度。&lt;/p&gt;

&lt;h3 id=&quot;construct-bit&quot;&gt;Construct BIT&lt;/h3&gt;

&lt;p&gt;如果&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;findLastBinaryOne&lt;/code&gt; 返回为1，数组中这个位置是BIT的叶子节点，只存储输入数列&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;在这个位置的值（例如在下图中的 index = 0, 2, 4, 6, …）的位置。&lt;/p&gt;

&lt;p&gt;如果&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;findLastBinaryOne(index)&lt;/code&gt;的返回是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; 且$n &amp;gt; 1$，在BIT中，这个位置的值等于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt;中这个位置的值加上&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIT[index - 2**0]&lt;/code&gt;， &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIT[index - 2 ** 1]&lt;/code&gt; … &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIT[index - 2 ** (n - 2)]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://markdown-img-1304853431.file.myqcloud.com/mark-markdown-imagebed-master/20210502162737.png&quot; alt=&quot;image-20201113173944215&quot; /&gt;&lt;/p&gt;

&lt;p&gt;假设我们计算BIT中一个位置的值（假设BIT树中前面的值都是正确的），我们可以这样写：&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getBITVal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//return the BIT value on i&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;power&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxPower&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;findLastBinaryOne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;power&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxPower&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;power&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;power&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;power&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;因为每次我们调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getBITVal&lt;/code&gt;函数的时候我们都假设&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIT&lt;/code&gt;中左侧的地方已经被初始好了，当我们初始化整个BIT时，我们需要从左到右的计算数组中每一个位置的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BIT&lt;/code&gt;值&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initializeBIT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++){&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getBITVal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;考虑到每次调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getBITVal&lt;/code&gt;都需要$O(\log{n})$的时间复杂度，我们初始化整个BIT数组的时间复杂度会是$O(n \log{n})$。虽然高于传统方法的$O(n)$，但是考虑到一般初始化代码只会执行一次，这个时间复杂度是可以接受的&lt;/p&gt;

&lt;h3 id=&quot;get-sum-from-bit&quot;&gt;Get Sum from BIT&lt;/h3&gt;

&lt;p&gt;我们现在已经有了BIT，那么我们怎么使用它查询一个区间内的元素和呢？首先，我们先看如何通过BIT查询 0 - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt;的区间和。观察上面的图，我们不难发现，一个BIT并不是单独的一棵树，而是很多棵子树所构成的，每个子树的根节点代表它所有叶子节点的和。那么，如果我们要计算0 - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt;的区间和的话，我们只需要找到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt;的二进制，然后每次去掉其中排在最后的一个1即可。（对应的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt;前的根节点）&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;例子：如果我们需要计算 0 - 6之间的区间和，我们要 …&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;binary (6 + 1)  = 1011&lt;/li&gt;
    &lt;li&gt;sum = tree[1011] + tree[1010] + tree[1000] = tree[7] + tree[6] + tree[4]&lt;/li&gt;
  &lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;用java代码表示，就是这样：&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getSum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;endIndex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;findLastBinaryOne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;注意到循环的执行次数最大为索引二进制数的长度，也就是$\log_2{\text{index}}$，这说明调用一次&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getSum&lt;/code&gt;函数只会有$O(\log{n})$的时间复杂度&lt;/p&gt;

&lt;p&gt;有了从0到index的区间和，我们就可以很方便的计算出任意两个索引之间的区间和（因为同是求区间和，这里直接重载了之前的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getSum&lt;/code&gt;函数）&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getSum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;startIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSum&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;startIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;update-bit-tree&quot;&gt;Update BIT Tree&lt;/h3&gt;

&lt;p&gt;前文提到过BIT最大的优势是在保证快速求出区间和的同时可以快速进行数据结构的更新，接下来我们看看BIT是怎么进行数据结构的更新的：&lt;/p&gt;

&lt;p&gt;如果我们想要更改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this.val&lt;/code&gt;中的数据，我们必须更新其对应的树结构。因为BIT中兄弟节点是互不影响的，我们只用更新被更新索引所在的BIT树的所有父节点就可以了。&lt;/p&gt;

&lt;p&gt;因为树的高度取决于索引二进制的长度，总共需要更新的节点数量的上限为$O(\log{n})$，用Java代码可以这样写：&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getParents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currStep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;findLastBinaryOne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currStep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updatePoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newVal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newVal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newVal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++){&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tree&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getBITVal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;（&lt;em&gt;上面的代码因为每个父节点更新都调用了一次&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getBITval&lt;/code&gt;函数，实际上的时间复杂度是$O((\log{n})^2)$， 通过修改实现方式，我们可以达到 $O(\log{n})$ 的时间复杂度&lt;/em&gt;）&lt;/p&gt;

&lt;h2 id=&quot;练习&quot;&gt;练习&lt;/h2&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://usaco.org/index.php?page=viewproblem2&amp;amp;cpid=719&quot;&gt;USACO 2017 Feb Problem 3. Why Did the Cow Cross the Road III&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://usaco.org/index.php?page=viewproblem2&amp;amp;cpid=693&quot;&gt;USACO 2017 Jan Problem 1. Balanced Photo&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=1041&quot;&gt;USACO 2020 US Open Contest, Gold Problem 1. Haircut&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;更多&quot;&gt;更多&lt;/h2&gt;

&lt;p&gt;&lt;button class=&quot;main-button&quot; onclick=&quot;window.location.href='https://www.geeksforgeeks.org/two-dimensional-binary-indexed-tree-or-fenwick-tree/'&quot;&gt;二维 Binary Index Tree&lt;/button&gt;&lt;/p&gt;
</description>
				<pubDate>Sun, 09 May 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/05/09/Binary-Index-Tree.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/05/09/Binary-Index-Tree.html</guid>
			</item>
		
			<item>
				<title>最小生成树 Min-Span Tree</title>
				<description>&lt;h3 id=&quot;最小生成树&quot;&gt;最小生成树&lt;/h3&gt;

&lt;p&gt;假设要在国际部的每个教室间接网线，每条网线只能直接连接两间教室，如何才能用最少的网线，让所有的教室都连通？&lt;/p&gt;

&lt;p&gt;这是一个很典型的最小生成树问题。对于一个图，你需要找到一组 edge, 使得所有的 vertex 都连通，同时 cost 最少。解决这个问题通常会使用 Kruskal 或者 Prim 算法。&lt;/p&gt;

&lt;p&gt;Prim 算法的思路是这样的，我把所有的节点分成两个部分，一部分是已经在最小生成树上的节点，一部分是还没添加的节点。当我需要添加一个节点时，我要找出剩下的节点中，离已有的书直接相连并且 cost 最低的点。不断重复这个过程直到所有的点都添加到了树上。&lt;/p&gt;

&lt;h3 id=&quot;伪代码&quot;&gt;伪代码&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;T = {s}
将 s 的所有 edge 都添加到优先队列 PQ 中
当 PQ 不为空时:
  v, cost = PQ.pop()
  如果 v 不在 T 中:
    将 v 加入 T
    将所有 v 的 edge 都加入到 PQ
T
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;代码实现&quot;&gt;代码实现&lt;/h3&gt;

&lt;pre&gt;
&lt;code class=&quot;python&quot;&gt;
def prim(graph, start=0):
  &quot;&quot;&quot; 
  生成 graph 的 prim

    参数:
      graph: 你要处理的图
      start: 表示从哪个 vertex 开始生成，对于一般情况来说，从哪个 vertex 开始都一样，默认从 0 号开始
  &quot;&quot;&quot;
  MAX_INT = 9999999
  distance = [MAX_INT] * graph.getNumVertices() # distance 表示的是所有 vertex 到最小生成树任意节点的最小 cost，初始化为正无穷
  isInTree = [False] * graph.getNumVertices() # isInTree 表示 vertex 是否在树上

  vertex = start # vertex 表示当前要添加进树的节点
  distance[vertex] = 0
  while not isInTree[vertex]:
    isInTree[vertex] = True

    # 枚举 vertex 的所有邻居，如果需要的话更新它们到树的距离
    for (neighbor, cost) in graph.getNeighbors(vertex):
      if not isInTree(neighbor):
        distance[neighbor] = min(distance[neighbor], cost)

    # 找出下一个要添加的 vertex
    minCost, minVertex = MAX_INT, 0
    for (v, cost) in enumerate(distance):
      if (not isInTree[v]) and cost &amp;lt; minCost:
        minCost, minVertex = cost, v

    vertex = minVertex
&lt;/code&gt;
&lt;code class=&quot;java&quot;&gt;
    Not Implemented Yet
&lt;/code&gt;
&lt;/pre&gt;

&lt;h3 id=&quot;题目&quot;&gt;题目&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://vjudge.net/problem/UVA-1174&quot;&gt;UVA-1174 标准 MST 题目，只需要把名字转换成序号就可以了&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://vjudge.net/problem/UVA-1208&quot;&gt;UVA-1208 标准 MST 题目，注意输出要求顺序&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://vjudge.net/problem/UVA-908&quot;&gt;UVA-908 多加一点分析就可以把题目转化成基本的 MST&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
				<pubDate>Mon, 03 May 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/05/03/Min-Span-Tree.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/05/03/Min-Span-Tree.html</guid>
			</item>
		
			<item>
				<title>优先队列 Priority Queue</title>
				<description>&lt;h3 id=&quot;前置条件&quot;&gt;前置条件&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/03/02/Time-Complexity.html&quot;&gt;理论基础：时间复杂度 Time Complexity&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/05/10/Queue.html&quot;&gt;数据结构：队列 Queue&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;数据结构：最大堆，最小堆 Min/Max Heap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;优先队列&quot;&gt;优先队列&lt;/h3&gt;

&lt;p&gt;在日常生活中，大家也许遇到过下面这些情景 - 在堵车的时候，救护车和消防车可以优先通过拥堵路段；在排队的时候，一些人的优先级比别人的高…… 在这些情景中，我们既希望可以维持一个类似队列的结构，也希望能够为这个队列提供一定的灵活性 - 一些优先级高的内容可以优先出队列。&lt;/p&gt;

&lt;p&gt;优先队列就是专门设计用来解决这些问题的一种数据结构。正如他的名字所言，优先队列就是一个有优先级规则的队列。&lt;/p&gt;

&lt;h3 id=&quot;数据结构实现&quot;&gt;数据结构实现&lt;/h3&gt;

&lt;p&gt;一般我们会使用最小堆来实现优先队列。如果你还记得，一个最小堆实际上是一颗二叉树 - 在根节点处的值总是整个堆中的最小值，每个父节点都一定大于等于自己的子节点们。如果我们按照内容的优先级做排序就可以保证优先级最高的项目无论什么时候加入优先队列都会排在优先队列的第一位。&lt;/p&gt;

&lt;h3 id=&quot;代码实现&quot;&gt;代码实现&lt;/h3&gt;

&lt;pre&gt;
	&lt;code class=&quot;python&quot;&gt;
# Suppose we have the minHeap class already
class PriorityQueueItem:
	def __init__(self, priority, value):
		self.priority = priority
		self.val = value

	def __lt__(self, other):
		return self.priority &amp;lt; other.priority

	def __eq__(self, other):
		return self.priority == other.priority

	def __gt__(self, other):
		return self.priority &amp;gt; other.priority


class PriorityQueue:
	def __init__(self):
		self.heap = minHeap()

	def pushItem(value, priority=0):
		&quot;&quot;&quot;
		put Priority Queue Item into the Priority Queue, with default priority 0.
		&quot;&quot;&quot;
		self.heap.push(PriorityQueueItem(priority, value))

	def popItem():
		&quot;&quot;&quot;
		get item from Priority Queue
		&quot;&quot;&quot;
		return self.heap.pop().val

	def isEmpty():
		return self.heap.isEmpty()
	&lt;/code&gt;
	&lt;code class=&quot;java&quot;&gt;
Not Implemented Yet. See Python Version.
	&lt;/code&gt;
&lt;/pre&gt;

&lt;h3 id=&quot;实际使用&quot;&gt;实际使用&lt;/h3&gt;

&lt;p&gt;在实际的竞赛中，我们出于对速度和 debug 方面的考虑一般不会使用自己实现的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Priority Queue&lt;/code&gt;，而是会使用官方实现好的内置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Priority Queue&lt;/code&gt; 实现。 下面我们会介绍一下各个语言中 Priority Queue 的实际用法。&lt;/p&gt;

&lt;h4 id=&quot;python---heapq-内置库&quot;&gt;Python - heapq 内置库&lt;/h4&gt;

&lt;p&gt;在 Python 中，我们可以用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heapq&lt;/code&gt; 库实现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Priority Queue&lt;/code&gt;。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heapq&lt;/code&gt; 对于优先队列的实现与大部分数据结构不同 - 一般我们实现一个数据类型的时候，我们都会单独定义一个 class 来实现我们的数据结构，每次需要的时候对数据结构进行实例化。&lt;/p&gt;

&lt;p&gt;然而，在 heapq 中，Priority Queue 的实现使用了一种类似于函数式编程的思想 - 这个库并没有实现&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class PriorityQueue&lt;/code&gt;，而是设计了三个函数来对 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list&lt;/code&gt; 进行操作来“模拟”一个 Priority Queue。&lt;/p&gt;

&lt;p&gt;下面是三个非常常用的函数：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heapq.heappush(arr: list, element: Comparable) -&amp;gt; None&lt;/code&gt; 来向优先队列 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arr&lt;/code&gt; 添加元素&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heapq.heappop(arr: list) -&amp;gt; element&lt;/code&gt; 从优先队列&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arr&lt;/code&gt;中取出元素&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heapq.heapify(arr: list) -&amp;gt; None&lt;/code&gt; 对 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;list arr&lt;/code&gt; 中的元素重新排序，使 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arr&lt;/code&gt; 中的元素排序符合最小二分堆的要求&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;java---javautilpriorityqueue&quot;&gt;Java - java.util.PriorityQueue&lt;E&gt;&lt;/E&gt;&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html&quot;&gt;Oracle Java.util.PriorityQueue 官方文档&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Priority Queue 实例化方法&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PriorityQueue&amp;lt;T&amp;gt; a = new PriorityQueue&amp;lt;&amp;gt;();&lt;/code&gt; - 生成一个优先队列，其中的元素都是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class T&lt;/code&gt; 或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;class T&lt;/code&gt; 的子类。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PriorityQueue&amp;lt;T&amp;gt; a = new PriorityQueue&amp;lt;&amp;gt;(ComparatorT)&lt;/code&gt; - 实例化一个优先队列，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComparatorT&lt;/code&gt; 对优先队列中的元素进行排序。&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;info&quot;&gt;
	Java 中的 Priority Queue 默认是使用 &lt;code&gt;NaturalOrder&lt;/code&gt; 对队列中的元素进行排序的，如果需要使用自定义的比较器，需要在实例化 Priority Queue 的时候将比较器实例作为参数传入构造函数。
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Priority Queue 常用函数&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add(E object)&lt;/code&gt; - 添加一个元素到 Priority Queue 中&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;peek()&lt;/code&gt; - 在&lt;strong&gt;不将队列底部元素（下一个被 pop 出来的元素）移出&lt;/strong&gt; Priority Queue 的前提下查看队列底部。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poll()&lt;/code&gt; - 返回 Priority Queue 的底部元素并同时在 Priority Queue 内删除该元素&lt;/li&gt;
&lt;/ul&gt;
</description>
				<pubDate>Fri, 30 Apr 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/04/30/Priority-Queue.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/04/30/Priority-Queue.html</guid>
			</item>
		
			<item>
				<title>代价统一搜索 Uniform Cost Search</title>
				<description>&lt;h3 id=&quot;前置条件&quot;&gt;前置条件&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/03/02/Time-Complexity.html&quot;&gt;理论基础：时间复杂度 Time Complexity&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/05/10/Queue.html&quot;&gt;数据结构：队列 Queue&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/04/30/Priority-Queue.html&quot;&gt;数据结构：优先队列 Priority Queue&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;理论知识：图的表达 How to Represent a Graph&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/04/12/Breadth-First-Search.html&quot;&gt;算法：广度优先算法 Breadth First Search&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/04/12/Depth-First-Search.html&quot;&gt;算法：深度优先算法 Depth First Search&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;代价统一搜索策略&quot;&gt;代价统一搜索策略&lt;/h3&gt;

&lt;p&gt;在之前的&lt;a href=&quot;/2021/04/12/Depth-First-Search.html&quot;&gt;深度优先搜索&lt;/a&gt;和&lt;a href=&quot;/2021/04/12/Breadth-First-Search.html&quot;&gt;广度优先搜索&lt;/a&gt;中，我们一般都只考虑目标节点与出发节点之间的&lt;strong&gt;图上距离&lt;/strong&gt;&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;而非&lt;strong&gt;真实距离&lt;/strong&gt;&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; - 这在一些简单的场景下没有什么问题，但是在一些情况下图上的距离与真实距离并不一致。例如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://markdown-img-1304853431.file.myqcloud.com/mark-markdown-imagebed-master/20210319224716.jpg&quot; alt=&quot;6e5f63b38286cc81fc07f61886fabb9&quot; style=&quot;zoom:33%; display: block; margin: 0 auto&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在下面这张图中， $G$ 与 $S$ 之间的图上距离最小路径应该是直线 $A$。但是，如果我们要看 $G$ 和 $S$ 之间的路径权重之和最小的话我们会发现最优路径并不是 $A$ 而是 $A*$，因为 $A$ 的路径权重之和为 $10 + 5 = 15$ 而 $A*$ 的路径权重之和为 $1 + 2 + 1 + 1 = 5$。&lt;/p&gt;

&lt;p&gt;为了找到实际距离最短的路径而不是图上距离最短的路径，人们在 BFS 的基础上做出了改动，产生了更加准确的 &lt;strong&gt;UCS 代价统一搜索策略&lt;/strong&gt;。在 BFS 中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Queue&lt;/code&gt; 的性质距离初始节点图上距离最小的节点会优先被展开，而在 UCS 中，&lt;mark&gt;我们用 &lt;code&gt;Priority Queue&lt;/code&gt; 实现 Fringe，这个优先队列对待探索节点的排序是基于初始节点到待探索节点的实际距离决定的&lt;/mark&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://markdown-img-1304853431.file.myqcloud.com/mark-markdown-imagebed-master/20210430075002.png&quot; style=&quot;zoom:50%;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;一张图的 “等 Cost 线“&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;在 UCS 对图像进行遍历的过程中，如果在 Fringe 中 Actual Cost 最小的节点的 Actual Cost 为 $C$，则所有已探索的节点的 Actual Cost 都&lt;strong&gt;一定$\leq C$&lt;/strong&gt;。通过这个性质，我们可以轻易证明&lt;mark&gt;UCS找到的第一个目标节点一定是距离初始节点实际距离最小的目标节点（即最优解）&lt;/mark&gt;。&lt;/p&gt;

&lt;h3 id=&quot;代价统一算法的实现&quot;&gt;代价统一算法的实现&lt;/h3&gt;

&lt;pre&gt;
    &lt;code class=&quot;python&quot;&gt;
import heapq    # The Python Module for Priority Queue

def uniformCostSearch(initialState, getSuccessor, getValidActions, getActionCost):
    &quot;&quot;&quot;
    :param initialState: The Initial State of problem (sometimes the 'current state')
    :param getSuccessor: The State Transition Function that return the successors given the current state and action
    :param getValidActions: A function that takes current state and return a list of valid actions under current state
    :param getActionCost: A function that will return cost of action given action and current state
    &quot;&quot;&quot;
    fringe = []    # The only difference between BFS and DFS
    exploredStates = set()
    
    # Add the Initial State into the Fringe before Searching Actually Start.
    # Instead of storing state directly in the fringe, we will use a tuple to store state, where the 
    # 0th param of tuple is cumulative cost
    # 1th param of tuple is the state
    
    heapq.heappush(fringe, (0, initialState))	# The initial cost is 0
    while len(fringe) &amp;gt; 0:
    	cost, currState = heapq.heappop(fringe)
        if currState in exploredStates: continue
        else: exploredState.add(currState)
            
        # Do Something Here
        
        for action in getValidActions(currState):
            # Add Successor States into the fringe
            successor = getSuccessor(currState, action)
            if successor not in exploredStates:
                deltaCost = getActionCost(currrState, action)
                heapq.heappush((cost + deltaCost, successor))
    &lt;/code&gt;
    &lt;code class=&quot;java&quot;&gt;
Not Implemented Yet, see Python Version
    &lt;/code&gt;
&lt;/pre&gt;

&lt;h3 id=&quot;练习&quot;&gt;练习&lt;/h3&gt;

&lt;div class=&quot;notification&quot;&gt;暂无练习 （一般与其他算法搭配使用，很少有单独的练习出现，思考一下之前做过的一些 BFS / DFS 题目有没有可能用 UCS 取代原来的算法来优化？）&lt;/div&gt;

&lt;hr /&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;图上距离指节点之间的边的数量 &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;真实距离指节点之间的边的权重之和 &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
				<pubDate>Thu, 29 Apr 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/04/29/Uniform-Cost-Search.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/04/29/Uniform-Cost-Search.html</guid>
			</item>
		
			<item>
				<title>CS188 Chapter 5 Adversarial Search</title>
				<description>&lt;h3 id=&quot;51-games&quot;&gt;5.1 Games&lt;/h3&gt;

&lt;p&gt;This chapter describes the &lt;strong&gt;Competitive Environments&lt;/strong&gt; for agents, where their goals are conflict. Such problem is called the &lt;strong&gt;adversarial search&lt;/strong&gt; problems - often known as &lt;strong&gt;games&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the field of AI, the most common games are a special kind of game - the &lt;strong&gt;Deterministic, Turn-taking, Two-player, Zero-sum games&lt;/strong&gt; of &lt;strong&gt;Perfect Information&lt;/strong&gt; (such as chess).&lt;/p&gt;

&lt;p&gt;Games are interesting since they are hard to solve using direct search - the branching factor of game is too large that it is impossible to search through all possible states. Also, games penalize inefficiency severely so the program should be as fast as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pruning&lt;/strong&gt; （剪枝） allows us to ignore portions of search tree that make no difference to the final choice. Heuristic &lt;strong&gt;Evaluation Functions&lt;/strong&gt; allow us to approximate the true utility of a state without doing a complete search.&lt;/p&gt;

&lt;p&gt;Suppose there are two agents - “MAX” and “MIN”. In a game, “MAX” move first and they take turn to move until the game is over. The winner get points and loser get penalty.&lt;/p&gt;

&lt;h4 id=&quot;511-formally-defined-game&quot;&gt;5.1.1 Formally Defined Game&lt;/h4&gt;

&lt;p&gt;A game can be formally defined with these elements&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Element&lt;/th&gt;
      &lt;th&gt;Explanation&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;$S_0$&lt;/td&gt;
      &lt;td&gt;The Initial State of game (the setup of game)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$Player(s)$&lt;/td&gt;
      &lt;td&gt;Defines which player has a move in the current state $s$&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$Actions(s)$&lt;/td&gt;
      &lt;td&gt;Returns a list of legal actions in a state $s$&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$Result(s, a)$&lt;/td&gt;
      &lt;td&gt;The &lt;em&gt;state transition model&lt;/em&gt;, which defines the result of an action $a$&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$Terminal-Test(s)$&lt;/td&gt;
      &lt;td&gt;Returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; if the game is over, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; otherwise&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$Utility(s, p)$&lt;/td&gt;
      &lt;td&gt;A utility function defines the numeric value for a game that ends in terminal state $s$ for player $p$&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The &lt;strong&gt;Zero-sum&lt;/strong&gt; game is defined as one where the &lt;mark&gt;total payoff to all players is the same for every instance of the game&lt;/mark&gt;.&lt;/p&gt;

&lt;p&gt;The initial state $S_0$, $Action$ function and $Result$ function define the &lt;strong&gt;game tree&lt;/strong&gt; for the game - a tree where the nodes are game states and the edges are actions.&lt;/p&gt;

&lt;p&gt;In a game tree, we record the utility value of the terminal state from the point of view of $MAX$ agent.&lt;/p&gt;

&lt;p&gt;Though a game tree is well-defined and has finite amount of nodes in it, it is better thought to be a theoretical construct we can’t realize in physical world as it has too many nodes in it (the Go has $10^40$ nodes, tic-tac-toe has more than $3\times 10^5$ nodes). We usually use term &lt;strong&gt;search tree&lt;/strong&gt; to represent a tree that is extracted from the full game tree, and contains enough nodes to allow a player to determine what action to make.&lt;/p&gt;

&lt;h3 id=&quot;52-optimal-decision-in-games&quot;&gt;5.2 Optimal Decision in Games&lt;/h3&gt;

&lt;p&gt;In an adversarial search scene, the MAX agent must find a contingent &lt;strong&gt;strategy&lt;/strong&gt;. An optimal strategy leads to outcomes at least as good as other strategy when one is playing an infallible opponent.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://markdown-img-1304853431.file.myqcloud.com/mark-markdown-imagebed-master/20210422204817.png&quot; alt=&quot;image-20210422204817496&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In the graph above, the maximum utility at node $A$ is 3, since the MAX agent can’t change the choice of MIN agent, and in the worst situation (no matter which action MAX agent choose, MIN will always select the successor with min utility for MAX), the maximum utility at $A$ is 3, when MAX takes action $a_1$.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In game theory, we combine a move of MAX and a move of MIN as “one move”, and call two half-moves the “ply”.&lt;/p&gt;

&lt;p&gt;Given a game tree, the optimal strategy can be determined from the &lt;strong&gt;minimax value&lt;/strong&gt; of each node. The minimax value of a node is the utility for MAX at that state assuming that &lt;em&gt;both players play optimally from there to the end of the game&lt;/em&gt;.&lt;/p&gt;

\[MINMAX(s) = \begin{cases}
Utility(s) &amp;amp; \text{if }TERMINAL-TEST(s)\\
max_{a\in Action(s)}{MINIMAX(RESULT(s, a))} &amp;amp; \text{if }Player(s) = MAX\\
min_{a\in Action(s)}{MINIMAX(RESULT(s, a))} &amp;amp; \text{if }Player(s) = MIN\\
\end{cases}\]

&lt;p&gt;The image above shows the &lt;strong&gt;minimax decision&lt;/strong&gt; at the root of game tree: action $a_1$ is the optimal choice for MAX because it leads to the state with the highest minimax value. The minimax decision maximize the &lt;em&gt;worst-case&lt;/em&gt; outcome for MAX.&lt;/p&gt;

&lt;p&gt;Other strategies may do better than the minimax strategy when playing with sub-optimal agent, but in the worst case, they are necessarily worse than the minimax decision.&lt;/p&gt;

&lt;h4 id=&quot;521-minimax-algorithm&quot;&gt;5.2.1 Minimax Algorithm&lt;/h4&gt;

&lt;p&gt;The &lt;strong&gt;minimax algorithm&lt;/strong&gt; computes the minimax decision from the current state. The recurssion proceeds all the way down to the leaves of the tree, and then back up through the tree as the recurrsion call back.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;minValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    return the minimum utility that can achieve from state s assuming MAX agent is playing optimally
    we assume this is the utility that MIN agent's move will result to
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TERMINAL_TEST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UTILITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;minVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'inf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ACTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;minVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minVal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;maxValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RESULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minVal&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;maxValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    return the maximum utility that can achieve from state s assuming MIN agent is playing optimally
    we assume this is the utility that MAX agent's move will result to
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TERMINAL_TEST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UTILITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;maxVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'inf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ACTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;maxVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maxVal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;minValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RESULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxVal&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;minimaxDecision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Return the action that maximize the minimax value at s
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;resAction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;maxMinimax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'inf'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ACTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;minValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RESULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxMinimax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;maxMinimax&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;minValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RESULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;resAction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resAction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Though the game we discuss is zero-sum game, &lt;strong&gt;alliances&lt;/strong&gt; is still a possible choice. Collaboration may emerge from purely selfish behavior.&lt;/p&gt;

&lt;h3 id=&quot;53-alpha-beta-pruning&quot;&gt;5.3 Alpha-Beta Pruning&lt;/h3&gt;

&lt;p&gt;When we are using minimax decision algorithm, we have to travel through the game tree using DFS. The node we have to explore will grow exponentially as the depth of game tree grow. Though we can’t eliminate the exponential term in time complexity, &lt;mark&gt;we can effectively reduce its size by applying pruning methods&lt;/mark&gt;.&lt;/p&gt;

&lt;p&gt;Here, we will apply &lt;strong&gt;alpha-beta pruning&lt;/strong&gt; on the standard minimax tree. It will return the same move as minimax decision algorithm would and prunes away branches that can’t possibly influence the final decision.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://markdown-img-1304853431.file.myqcloud.com/mark-markdown-imagebed-master/20210423095210.png&quot; alt=&quot;image-20210423095210359&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The idea of alpha-beta pruning comes from a very simple observation - in some cases, we don’t need to find all successors’ utilities to calculate the minimax value at a node. For instance, in the fig above, when we see the maximum minimax value at $C$ is 2, we know its minimax value must be smaller than $B$’s minimax value (which is 3) and we can ignore the other two nodes (dash line) under $C$.&lt;/p&gt;

&lt;p&gt;If Player has a better choice than $n$, $n$ will &lt;em&gt;never be reached in actual play&lt;/em&gt;. Therefore, once we find enough information about $n$ to reach this conclusion, we can prune it.&lt;/p&gt;

&lt;p&gt;Below shows a general case for alpha-beta pruning:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://markdown-img-1304853431.file.myqcloud.com/mark-markdown-imagebed-master/20210423101148.png&quot; alt=&quot;image-20210423101148347&quot; /&gt;&lt;/p&gt;

&lt;p&gt;$\alpha=$ the minimax value of the best choice (max-value) we have found so far at any choice point along the path for MAX&lt;/p&gt;

&lt;p&gt;$\beta=$ the minimax value of the best choice (min-value) we have found so far at any choice point along the path for MIN&lt;/p&gt;

&lt;p&gt;Alpha-beta pruning update the $\alpha$ and $\beta$ as it goes along and prunes the remaining branches at a node as soon as the value of the current node is known to be worse than the current $\alpha$ or $\beta$ for MAX and MIN respectively.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;maxValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    returns an integer represent the minimax value at current state (or the last value before the node is pruned)
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TERMINAL_TEST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UTILITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;inf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ACTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;minValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RESULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# Since the MIN agent is optimal, this scnerio will never occur
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;# the following expansion is pruned
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;minValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    returns an integer represent the min minimax value at current state (or the last value before the node is pruned)
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TERMINAL_TEST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;UTILITY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;inf&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ACTION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;maxValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;RESULT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minimaxVal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Since the MAX agent is optimal, the MAX agent will never reach this node (as there exist better path)
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minimaxValue&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# the following expansion is pruned
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minimaxValue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To start searching from the root, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maxValue(root, -1 * float(&quot;inf&quot;), float(&quot;inf&quot;))&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;54-backtracking&quot;&gt;5.4 Backtracking&lt;/h3&gt;

&lt;p&gt;Backtracking is a way to prune the search space. When we are searching through a search space, sometimes we can make sure the current solution is impossible when we haven’t reach the end of action sequence.&lt;/p&gt;

&lt;p&gt;Suppose a game need 4 actions to make up an action sequence, we can sometimes know we will lose when playing only 2 actions yet. In this case, we can stop searching and &lt;strong&gt;go back to previous step&lt;/strong&gt; and choose another action to play. (this is the reason why it is called &lt;em&gt;Backtracking&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://markdown-img-1304853431.cos.ap-guangzhou.myqcloud.com/20210511000544.png&quot; alt=&quot;image-20210511000544052&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The effect of backtracking will be more significant if we can identify whether it is possible or not to get to goal node from a shallower node. In such situation, much of the search space will be pruned.&lt;/p&gt;

&lt;p&gt;A famous problem that can be solved by Backtracking is the “eight queens” problem. Detailed description of a more general case (n-queen problem) is in this link: &lt;a href=&quot;https://vjudge.net/problem/UVA-11195&quot;&gt;UVA-11195 Another n-Queen Problem&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;nQueen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currCol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currCol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;resultState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;candidate&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isValidState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;candidate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currCol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;newState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:]&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;newState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currCol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;candidate&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;resultState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;nQueen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currCol&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resultState&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isValidState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;candidate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currColumn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;candidate&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# are queens on the same row
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currColumn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;position&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;candidate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;currColumn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;                    &lt;span class=&quot;c1&quot;&gt;# are queens on the same diagonal
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
				<pubDate>Thu, 22 Apr 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/04/22/CS188-Chapter5.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/04/22/CS188-Chapter5.html</guid>
			</item>
		
			<item>
				<title>栈 Stack</title>
				<description>&lt;h3 id=&quot;前置条件&quot;&gt;前置条件&lt;/h3&gt;

&lt;p&gt;在学习这个知识点前，你应该先学习……&lt;/p&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/03/02/Time-Complexity.html&quot;&gt;理论基础：时间复杂度 Time Complexity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;栈&quot;&gt;栈&lt;/h3&gt;

&lt;p&gt;栈(stack)是一种用于收集数据的线性数据结构，主要有两个操作&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;放入(push): 将元素放进集合&lt;/li&gt;
  &lt;li&gt;取出(pop) : 将最后放入的元素取出&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;因为Stack的两个操作，我们也可以将Stack记为LIFO(last in, first out)，也叫后进先出。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://markdown-img-1304853431.file.myqcloud.com/mark-markdown-imagebed-master/20210415144351.png&quot; alt=&quot;img&quot; style=&quot;zoom: 67%;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在栈(stack)中，还有几种常见的方法：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;peek&lt;/code&gt;: 查看当前的栈最后的一个元素&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isEmpty&lt;/code&gt;: 判断当前栈是否是空的&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;代码实现&quot;&gt;代码实现&lt;/h3&gt;

&lt;pre&gt;
&lt;code class=&quot;python&quot;&gt;
class Stack:
    def __init__( self ):
        self.stack = []

    def push( self, item ):
        self.stack.append( item )
        return self.stack

    def pop( self ):
        if self.isempty(): return -1
        self.stack.pop()
        return self.stack

    def peek(self):
        return self.stack[ -1 ]

    def isempty(self):
        if len( self.stack ) == 0: return True
        return False
&lt;/code&gt;
&lt;code class=&quot;java&quot;&gt;
import java.util.ArrayList;

public class Stack {
    ArrayList&amp;lt;Integer&amp;gt; stack = new ArrayList&amp;lt;Integer&amp;gt;();

    public void push( int item ){
        stack.add( item );
    }

    public int pop(){
        if ( ! stack.isEmpty() ) {
            return stack.remove(stack.size() - 1);
        }
        return -1;
    }

    public int peek(){
        return stack.get( -1 );
    }

    public boolean isempty(){
        if ( stack.size() == 0 ) {
            return true;
        }
        return false;
    }
}
&lt;/code&gt;
&lt;/pre&gt;

&lt;h3 id=&quot;时间复杂度-time-complexity&quot;&gt;时间复杂度 Time Complexity&lt;/h3&gt;

&lt;p&gt;栈的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pop&lt;/code&gt; 方法的时间复杂度都是 $O(1)$，因为每次将一个 object 放入栈中的时候，我们只需要在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayList&lt;/code&gt; 末尾添加一个元素即可。每次从栈中取出一个 object，我们只是读取 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayList&lt;/code&gt; 末尾的元素并删除而已。&lt;/p&gt;
</description>
				<pubDate>Thu, 15 Apr 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/04/15/Stack.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/04/15/Stack.html</guid>
			</item>
		
			<item>
				<title>深度优先搜索 Depth First Search</title>
				<description>&lt;h3 id=&quot;前置条件&quot;&gt;前置条件&lt;/h3&gt;

&lt;p&gt;在学习这个知识点前，你应该先学习……&lt;/p&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/03/02/Time-Complexity.html&quot;&gt;理论基础：时间复杂度 Time Complexity&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/05/10/Queue.html&quot;&gt;数据结构：队列 Queue&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/04/15/Stack.html&quot;&gt;数据结构：栈 Stack&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;理论知识：图的表达 How to Represent a Graph&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/04/12/Breadth-First-Search.html&quot;&gt;算法：广度优先算法 Breadth First Search&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;深度优先算法&quot;&gt;深度优先算法&lt;/h3&gt;

&lt;p&gt;搜索实际上可以看作遍历图的所有节点，直到遇到目标节点为止的过程。深度优先搜索在遍历的过程中遵循这样的规则：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;在所有待遍历的节点中，最深的节点最先被探索&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这里的“深”指的是节点到开始探索的节点的距离（边的数量）。注意：与&lt;a href=&quot;/2021/04/12/Breadth-First-Search.html&quot;&gt;广度优先算法&lt;/a&gt;不同的地方在于&lt;mark&gt;深度优先算法不能保证找到的目标节点是最浅（最优）的&lt;/mark&gt;。&lt;/p&gt;

&lt;h3 id=&quot;深度优先算法的实现&quot;&gt;深度优先算法的实现&lt;/h3&gt;

&lt;p&gt;与 BFS 不同，在 DFS 中我们要维护一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;queue&lt;/code&gt; 来作为 Fringe 存储待探索的节点。&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;python&quot;&gt;
def depthFirstSearch(initialState, getSuccessor, getValidActions):
    &quot;&quot;&quot;
    :param initialState: The Initial State of problem (sometimes the 'current state')
    :param getSuccessor: The State Transition Function that return the successors given the current state and action
    :param getValidActions: A function that takes current state and return a list of valid actions under current state
    &quot;&quot;&quot;
    fringe = queue()    # The only difference between BFS and DFS
    exploredStates = set()
    
    # Add the Initial State into the Fringe before Searching Actually Start.
    fringe.push(initialState)
    while len(fringe) &amp;gt; 0:
		currState = fringe.pop()
        exploredState.add(currState)
            
        # Do Something Here
        
        for action in getValidActions(currState):
            # Add Successor States into the fringe
            successor = getSuccessor(currState, action)
            if successor not in exploredStates: fringe.push(successor)
&lt;/code&gt;
&lt;code class=&quot;java&quot;&gt;
Not Implemented Yet. See Python Version.
&lt;/code&gt;
&lt;/pre&gt;

&lt;h3 id=&quot;深度优先算法的复杂度&quot;&gt;深度优先算法的复杂度&lt;/h3&gt;

&lt;h4 id=&quot;时间复杂度&quot;&gt;时间复杂度&lt;/h4&gt;

&lt;p&gt;深度优先算法的时间复杂度与广度优先算法的时间复杂度相同 - 是 $O(E + V)$，具体的解释和广度优先搜索的基本一致（使用 双向链表&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deque&lt;/code&gt; 实现的 queue 在取出节点时的时间复杂度也是 $O(1)$），所以直接 quote 过来。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;假设我们要在图 $G(V, E)$ （图 $G$ 有 $V$ 个节点，$E$ 条边）上使用广度优先算法进行遍历，算法最多只会遍历所有节点&lt;em&gt;1次&lt;/em&gt;（不会出现重复查看的情况），如果 Fringe 的 Stack 是用双头链表 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deque&lt;/code&gt; 实现的，那么每次从 Fringe 中取出节点的时间复杂度是 $O(1)$。这总共贡献了 $O(V)$ 的时间复杂度。因为每一条边只会在一端的节点被探索到时被查看一次，所以边最多被探索 $2E$ 次。每次探索一条边（因为是从 dictionary 中取出）只会有 $O(1)$ 的时间复杂度，所以探索边的总时间复杂度是 $O(2E) = O(E)$。&lt;/p&gt;

  &lt;p&gt;综上所述，BFS 的时间复杂度是 $O(V + E)$&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;空间复杂度&quot;&gt;空间复杂度&lt;/h4&gt;

&lt;p&gt;假设我们在图 $G$ 上运行DFS，在 $G$ 中平均每个节点有 $\alpha$ 个子节点，目标节点在第 $n$ 层，那么当探索到目标节点时，算法的空间复杂度应该是 $Space(\alpha, n) = n \times (\alpha - 1)$，也就是 $O(n\alpha)$。&lt;/p&gt;

&lt;p&gt;注意到这个空间复杂度比 BFS 的 $O(\alpha^n)$ 要好非常多倍，我们在已知目标节点深度较深或者图的 $\alpha$ 值较大时应该优先选择 DFS。&lt;/p&gt;

&lt;h3 id=&quot;练习&quot;&gt;练习&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/maximum-depth-of-n-ary-tree/&quot;&gt;[Easy] LeetCode Problem 559. Maximum Depth of N-ary Tree&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/path-sum/&quot;&gt;[Easy] LeetCode Problem 112. Path Sum&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/find-largest-value-in-each-tree-row/&quot;&gt;[Medium] LeetCode Problem 515. Find Largest Value in Each Tree Row&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=944&quot;&gt;[Medium] USACO 2019 Silver, Open P3 Fence Planning&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
				<pubDate>Mon, 12 Apr 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/04/12/Depth-First-Search.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/04/12/Depth-First-Search.html</guid>
			</item>
		
			<item>
				<title>广度优先搜索 Breadth First Search</title>
				<description>&lt;h3 id=&quot;前置条件&quot;&gt;前置条件&lt;/h3&gt;

&lt;p&gt;在学习这个知识点前，你应该先学习……&lt;/p&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/03/02/Time-Complexity.html&quot;&gt;理论基础：时间复杂度 Time Complexity&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/05/10/Queue.html&quot;&gt;数据结构：队列 Queue&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;/2021/04/15/Stack.html&quot;&gt;数据结构：栈 Stack&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;理论知识：图的表达 How to Represent a Graph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;广度优先搜索策略&quot;&gt;广度优先搜索策略&lt;/h3&gt;

&lt;p&gt;搜索实际上可以看作遍历图的所有节点，直到遇到目标节点为止的过程。广度优先搜索在遍历的过程中遵循这样的规则：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;在所有待遍历的节点中，最浅的节点最先被探索&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这里的“浅”指的是节点到开始探索的节点的距离（边的数量）。 因为广度优先搜索总是优先探索浅的节点，如果算法正在探索深度为 $h$ 的节点，那么所有深度小于 $h$ 的节点都&lt;em&gt;一定已经被探索了&lt;/em&gt;。&lt;/p&gt;

&lt;p&gt;也就是说，&lt;mark&gt;如果整个图中存在多个目标节点，那么BFS找到的第一个目标节点&lt;b&gt;一定&lt;/b&gt;是距离初始节点最近的节点。&lt;/mark&gt;&lt;/p&gt;

&lt;h3 id=&quot;广度优先搜索的实现&quot;&gt;广度优先搜索的实现&lt;/h3&gt;

&lt;p&gt;在广度优先搜索的过程中，我们需要维护一个 Stack，其中保存着所有与已探索节点相邻但是还没有探索的节点，这样的一个数据结构被称作 Fringe （已探索部分的边缘）。在探索 $h-1$ 层节点的时候， $h$ 层的节点会被放入 Fringe 中，只有在探索完 $h-1$ 层的节点以后才会探索 $h$ 层的节点。这时候，所有 $h$ 层的节点都已经被探索或者在 Fringe 中了，所以后面压入栈的 $h+1$ 层节点一定会比 $h$ 层节点更晚被探索。&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;python&quot;&gt;
def breadthFirstSearch(initialState, getSuccessor, getValidActions):
    &quot;&quot;&quot;
    :param initialState: The Initial State of problem (sometimes the 'current state')
    :param getSuccessor: The State Transition Function that return the successors given the current state and action
    :param getValidActions: A function that takes current state and return a list of valid actions under current state
    &quot;&quot;&quot;
    fringe = stack()
    exploredStates = set()
    
    # Add the Initial State into the Fringe before Searching Actually Start.
    fringe.push(initialState)
    while len(fringe) &amp;gt; 0:
        currState = fringe.pop()
        exploredState.add(currState)
            
        # Do Something Here
        
        for action in getValidActions(currState):
            # Add Successor States into the fringe
            successor = getSuccessor(currState, action)
            if successor not in exploredStates: fringe.push(successor)
&lt;/code&gt;
&lt;code class=&quot;java&quot;&gt;
    Not Implemented Yet. See Python Version of BFS.
&lt;/code&gt;
&lt;/pre&gt;

&lt;h3 id=&quot;广度优先算法的复杂度&quot;&gt;广度优先算法的复杂度&lt;/h3&gt;

&lt;h4 id=&quot;时间复杂度&quot;&gt;时间复杂度&lt;/h4&gt;

&lt;p&gt;假设我们要在图 $G(V, E)$ （图 $G$ 有 $V$ 个节点，$E$ 条边）上使用广度优先算法进行遍历，算法最多只会遍历所有节点&lt;em&gt;1次&lt;/em&gt;（不会出现重复查看的情况），如果 Fringe 的 Stack 是用双头链表 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deque&lt;/code&gt; 实现的，那么每次从 Fringe 中取出节点的时间复杂度是 $O(1)$。这总共贡献了 $O(V)$ 的时间复杂度。因为每一条边只会在一端的节点被探索到时被查看一次，所以边最多被探索 $2E$ 次。每次探索一条边（因为是从 dictionary 中取出）只会有 $O(1)$ 的时间复杂度，所以探索边的总时间复杂度是 $O(2E) = O(E)$。&lt;/p&gt;

&lt;p&gt;综上所述，BFS 的时间复杂度是 $O(V + E)$&lt;/p&gt;

&lt;h4 id=&quot;空间复杂度&quot;&gt;空间复杂度&lt;/h4&gt;

&lt;p&gt;假设图 $G$ 中平均一个节点会连接到 $\alpha$ 个子节点，目标节点在第 $n$ 层，那么BFS的空间复杂度会是 $O(\alpha^n)$。&lt;/p&gt;

&lt;p&gt;从这里我们也可以看出 BFS 并 &lt;strong&gt;不适合在目标节点很深的情况下使用&lt;/strong&gt;，如果目标节点在 28 层，即使 $\alpha = 2$，每个节点只占一个 32 位 int 的大小，内存也会占用 $1G$ 的大小来存放 Fringe，而 USACO 等算法竞赛的内存上限一般是 $256M$。&lt;/p&gt;

&lt;h3 id=&quot;练习&quot;&gt;练习&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/minimum-depth-of-binary-tree/&quot;&gt;[Easy] LeetCode Problem 111. Minimum Depth of Binary Tree&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/maximum-level-sum-of-a-binary-tree/&quot;&gt;[Medium] LeetCode Problem 1161. Maximum Level Sum of a Binary Tree&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/number-of-islands/&quot;&gt;[Medium] LeetCode Problem 200. Number of Islands&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=620&quot;&gt;[Medium] USACO 2016 Feb Silver P3 - Milk Pails&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=671&quot;&gt;[Hard] USACO 2016 December Contest, Gold Problem 3. Lasers and Mirrors&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=695&quot;&gt;[Hard] USACO 2017 January Contest, Gold Problem 3. Cow Navigation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;参考书目&quot;&gt;参考书目&lt;/h3&gt;

&lt;p&gt;《算法导论》Chapter 22.2 Breadth First Search&lt;/p&gt;
</description>
				<pubDate>Mon, 12 Apr 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/04/12/Breadth-First-Search.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/04/12/Breadth-First-Search.html</guid>
			</item>
		
			<item>
				<title>数组的排序</title>
				<description>&lt;div class=&quot;notification&quot;&gt;
&lt;p&gt;注意，这个页面并不是描述排序算法的页面。这个页面描述的是各个语言具体如何实现对数组的排序。如果你想看排序算法相关的内容，点击&lt;a href=&quot;/2021/02/22/Sorting.html&quot;&gt;这里&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;h3&gt;前置条件&lt;/h3&gt;
&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
    &lt;li&gt;&lt;offline&gt;&lt;/offline&gt;&lt;a href=&quot;&quot;&gt;数据结构：列表 Array (List) and ArrayList&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;section class=&quot;java&quot;&gt;
&lt;p&gt;在 Java 中，一般我们只会对 &lt;code&gt;ArrayList&lt;/code&gt; 中的对象进行排序操作。在对数组排序时，我们会使用 &lt;code&gt;ArrayList.sort&lt;/code&gt; 方法。这个方法&lt;strong&gt;不会有返回值&lt;/strong&gt;，会直接在原来的 ArrayList 上进行修改。&lt;/p&gt;

&lt;h3&gt;在 Java 中对语言自带的类型进行排序&lt;/h3&gt;

&lt;p&gt;如果我们要对数组进行排序，仅仅调用 &lt;code&gt;ArrayList.sort()&lt;/code&gt; 是不够的，我们还要告诉 Java 如何对 List 中的对象进行排序 - 这里我们就要引入 &lt;code&gt; Comparator &lt;/code&gt; 的概念了。Comparator 对象是专门用来比较两个对象大小的。&lt;code&gt;ArrayList&lt;/code&gt; 进行排序的时候会调用传入的 &lt;code&gt;Comparator&lt;/code&gt; 对象进行排序。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
import java.util.*;

public class compareExample {
    public static void main(String[] args) {
        ArrayList&amp;lt;Integer&amp;gt; arr = new ArrayList&amp;lt;&amp;gt;();
        arr.add(1);
        arr.add(8);
        arr.add(3);
        arr.add(5);
        arr.sort(Comparator.naturalOrder());
        System.out.println(arr);    // Output: [1, 3, 5, 8]
        arr.sort(Comparator.reverseOrder());
        System.out.println(arr);    // Output: [8, 5, 3, 1]
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在上面这段代码中，我们向 arr 传入了 &lt;code&gt;Comparator.naturalOrder()&lt;/code&gt; 这样一个对象。如同它的名字所描述的，这个比较器的作用就是将Array中的内容按照“自然顺序”排列 - 也就是从小到大的顺序。类似&lt;code&gt;naturalOrder&lt;/code&gt;，&lt;code&gt;java.util.Comparator&lt;/code&gt; 中还有其他的比较器，例如 &lt;code&gt;reverseOrder&lt;/code&gt; （将List中的元素从大到小的排序）等。&lt;/p&gt;

&lt;p&gt;如果你想排序的 ArrayList 中存放的元素是 Java 已给出的数据类型，那么对它们进行排序就只需要上面这一步就好了。然而，如果你想对自己声明的类型进行排序，我们还需要做一些额外的工作……&lt;/p&gt;

&lt;h3&gt;在 Java 中对自己定义的类进行排序&lt;/h3&gt;

&lt;p&gt;如果你想对自己定义的类进行排序，那么有以下两种方法实现：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在自己的类中实现 Java 定义的 &lt;code&gt;Comparable&lt;/code&gt; 接口&lt;/li&gt;
&lt;li&gt;自己为自己的类实现一个 &lt;code&gt;Comparator&lt;/code&gt; 类型，并将这个 Comparator 传到 &lt;code&gt;arr.sort()&lt;/code&gt; 中。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;下面，假设我们要对这样一个 Java 类进行排序：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
class Person{
    public int age;
    public String name;

    public Person(int age, String name){
        this.age = age;
        this.name = name;
    }

    public String toString(){
        return &quot;( age: &quot; + this.age + &quot;, name: &quot; + this.name + &quot; )&quot;;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;实现 Comparable 接口 （推荐）&lt;/h4&gt;
&lt;p&gt;通过实现 Comparable 接口，Java会识别到这个类是“可比较的”。在调用 &lt;code&gt;ArrayList.sort()&lt;/code&gt;的时候，&lt;code&gt;Comparator&lt;/code&gt;会调用你的类中的 &lt;code&gt;compareTo&lt;/code&gt;方法来判断两个对象之间的大小关系。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
public int compareTo(object other){
    /*
        If this object is bigger than the &quot;other&quot; given in the parameter, return a positive integer.
        if this object is smaller than the &quot;other&quot; given in parameter, return a negative integer.
        Otherwise, return 0.
    */
}
&lt;/code&gt;&lt;/pre&gt;
具体的写法如下：
&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
class Person implements Comparable&amp;lt;Person&amp;gt;{
    public int age;
    public String name;

    public Person(int age, String name){
        this.age = age;
        this.name = name;
    }

    public int compareTo(Person other){
        if (this.equals(other)){ return 0; }
        if (this.age != other.age){ return this.age - other.age; }
        else{ return this.name.compareTo(other.name); }
    }

    public boolean equals(Person other){
        return this.age == other.age &amp;amp;&amp;amp; this.name.equals(other.name);
    }

    public String toString(){
        return &quot;( age: &quot; + this.age + &quot;, name: &quot; + this.name + &quot; )&quot;;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你在自己的Java类上实现了&lt;code&gt;Comparable&lt;/code&gt; 接口，那么在数组排序时所有 &lt;code&gt;java.util.Comparator&lt;/code&gt; 中的比较器都可以直接传入给 &lt;code&gt;ArrayList&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
import java.util.*;

public class compareTest{
    public static void main(String[] args) {
        ArrayList&amp;lt;Person&amp;gt; arr = new ArrayList&amp;lt;&amp;gt;();
        arr.add(new Person(17, &quot;Mark&quot;));
        arr.add(new Person(14, &quot;Test&quot;));
        arr.add(new Person(18, &quot;wyn&quot;));
        arr.sort(Comparator.naturalOrder());
        System.out.println(arr);
    }
}
&lt;/code&gt;&lt;/pre&gt;
运行结果：
&lt;pre&gt;
[( age: 14, name: Test ), ( age: 17, name: Mark ), ( age: 18, name: wyn )]
&lt;/pre&gt;
&lt;h4&gt;实现 Comparator 类型 （不推荐）&lt;/h4&gt;
&lt;p&gt;除了直接实现&lt;code&gt;Comparable&lt;/code&gt;接口以外，我们还可以直接定义一个可以比较两个自己类型对象的比较器（Comparator）来达到对存储这个类型对象的数组进行排序的目的。这种情况下，我们要新建一个比较器类型来实现 Comparator 抽象类。Comparator 抽象类只有一个函数 - &lt;code&gt;compare&lt;/code&gt;。所以如果我们想实现一个效果和上文的方案相同的比较器，我们可以这样写：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
class PersonComparator implements Comparator&amp;lt;Person&amp;gt;{
    public int compare(Person o1, Person o2){
        if (o1 == o2){ return 0; }
        if (o1.age != o2.age) { return o1.age - o2.age; }
        else{ return o1.name.compareTo(o2.name); }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种情况下，我们要对&lt;code&gt;Person&lt;/code&gt;类进行排序就需要将自己定义的比较器传入&lt;code&gt;ArrayList.sort()&lt;/code&gt;中来进行排序。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;java&quot;&gt;
import java.util.*;

public class compareTest{
    public static void main(String[] args) {
        ArrayList&amp;lt;Person&amp;gt; arr = new ArrayList&amp;lt;&amp;gt;();
        arr.add(new Person(17, &quot;Mark&quot;));
        arr.add(new Person(14, &quot;Test&quot;));
        arr.add(new Person(18, &quot;wyn&quot;));
        arr.sort(new PersonComparator());
        System.out.println(arr);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出结果如下：&lt;/p&gt;
&lt;pre&gt;
[( age: 14, name: Test ), ( age: 17, name: Mark ), ( age: 18, name: wyn )]
&lt;/pre&gt;
&lt;/section&gt;
&lt;section class=&quot;python&quot;&gt;
&lt;h3&gt;Python 对元组和内置数据类型的排序&lt;/h3&gt;
&lt;p&gt;对于 Python 来说，数组的排序会变得简单很多：在Python中，你可以随意创建含有多个不同类型元素的数据对象 - Tuple (元组）。Python在比较元组大小时会先比较第0位大小，如果大小相同比较第1位……依此类推，直到找到最后一位或者大小不同的一位为止。&lt;/p&gt;
&lt;p&gt;例子：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
arr = [(1, &quot;test&quot;), (10, &quot;ebc&quot;), (10, &quot;abc&quot;), (3, &quot;wasd&quot;)]
arr.sort()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结果：&lt;/p&gt;
&lt;pre&gt;[(1, 'test'), (3, 'wasd'), (10, 'abc'), (10, 'ebc')]&lt;/pre&gt;

&lt;h3&gt;Python 对自己写的类进行排序&lt;/h3&gt;
&lt;p&gt;如果你试着直接对一个装有自己写的类的对象进行排序，Python会丢出这样的报错：&lt;/p&gt;
&lt;pre&gt;
Traceback (most recent call last):
  File &quot;d:\Python_Files\prime\compareV1.py&quot;, line 8, in &amp;lt;module&amp;gt;
    ...
TypeError: '&amp;gt;' not supported between instances of 'Person' and 'Person'
&lt;/pre&gt;
&lt;p&gt;这是因为我们没有规定如何比较两个 Person 对象之间的大小关系。和Java类似，在Python中也有两种方法对自己写的类进行排序。&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;为自己的类实现 &lt;code&gt;__gt__&lt;/code&gt;, &lt;code&gt;__lt__&lt;/code&gt;, &lt;code&gt;__eq__&lt;/code&gt; 等方法使类的对象之间支持比较大小&lt;/li&gt;
    &lt;li&gt;在 arr.sort 时手动写入一个&lt;code&gt;Comparator&lt;/code&gt;函数用来比较两个对象的大小关系，以 keyword arguement 形式将这个函数传入&lt;code&gt;sort&lt;/code&gt;方法。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;假设我们要对装有这样一个类的对象的数组进行排序……&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
class Person:
    def __init__(self, age, name):
        self.age = age
        self.name = name
        
    def __repr__(self):
        return &quot;(age: {}, name: {})&quot;.format(self.age, self.name)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;实现Python内置的，用于比较大小的方法&lt;/h4&gt;
&lt;p&gt;这种方法和 Java 中为自己的类实现 Comparable 接口非常相似，唯一的不同是&lt;strong&gt;没有显式的表明自己实现了Comparable接口/功能&lt;/strong&gt;。 Python 中一共有五个内置的，用于比较对象之间大小关系的函数：&lt;code&gt;__gt__&lt;/code&gt;, &lt;code&gt;__lt__&lt;/code&gt;, &lt;code&gt;__eq__&lt;/code&gt;, &lt;code&gt;__ge__&lt;/code&gt;, &lt;code&gt;__le__&lt;/code&gt;，分别对应大于，小于，相等，大于等于 和 小于等于 的判断。这里我们只需要实现前三个函数就好了。这三个函数返回一个布尔值，表明自己和传入的对象之间的关系是否是函数名所描述的关系。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
class Person:
    def __init__(self, age, name):
        self.age = age
        self.name = 
    
    def __repr__(self):
        return &quot;(age: {}, name: {})&quot;.format(self.age, self.name)
    
    def __lt__(self, otherPerson):
        if self.age != otherPerson.age: return self.age &amp;lt; otherPerson.age
        else: return self.name &amp;lt; otherPerson.name
    
    def __gt__(self, otherPerson):
        if self.age != otherPerson.age: return self.age &amp;gt; otherPerson.age
        else: return self.name &amp;gt; otherPerson.name
    
    def __eq__(self, otherPerson):
        return self.age == otherPerson.age and self.name == otherPerson.name
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;效果：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
arr = [Person(23, &quot;test1&quot;), Person(17, &quot;John&quot;), Person(19, &quot;Penny&quot;), Person(21, &quot;Mary&quot;), Person(23, &quot;test2&quot;)]
arr.sort()
print(arr)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;
[(age: 17, name: John), (age: 19, name: Penny), (age: 21, name: Mary), (age: 23, name: test1), (age: 23, name: test2)]
&lt;/pre&gt;

&lt;h4&gt;向 &lt;code&gt;List.sort()&lt;/code&gt;传入比较方法&lt;/h4&gt;

&lt;p&gt;在我们调用sort方法时，有一个隐藏的 keyword arguement 是 &lt;code&gt;key = function&lt;/code&gt;。这里的 &lt;code&gt;function&lt;/code&gt; 是一个函数。如果这个参数被传递进了 sort 方法，那么在sort在比较大小时，Python会先将list中的对象传入 &lt;code&gt;function&lt;/code&gt;，然后根据函数返回值进行排序。例如我们只想通过 Person 的 age 属性对 Person 对象进行排序，那么我们可以用这样一个 lambda 函数作为 key 传入 sort 方法。（注意：这时候即使 Person 没有实现 &lt;code&gt;__lt__&lt;/code&gt;, &lt;code&gt;__gt__&lt;/code&gt;, &lt;code&gt;__eq__&lt;/code&gt; 方法也可以进行排序。）&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
arr = [Person(23, &quot;test1&quot;), Person(17, &quot;John&quot;), Person(19, &quot;Penny&quot;), Person(21, &quot;Mary&quot;), Person(23, &quot;test2&quot;)]
arr.sort(key= lambda personObj: personObj.age)
print(arr)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;当然，如果 key 所对应的函数逻辑较为复杂，也可以在外面定义完以后再传入key参数。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;
def convertPerson(personObj):
    # convert a person object into a comparable object
    return str(personObj.age) + personObj.name

arr = [Person(23, &quot;test1&quot;), Person(17, &quot;John&quot;), Person(19, &quot;Penny&quot;), Person(21, &quot;Mary&quot;), Person(23, &quot;test2&quot;)]
arr.sort(key = convertPerson)
print(arr)
&lt;/code&gt;&lt;/pre&gt;

&lt;/section&gt;

&lt;h3&gt;练习&lt;/h3&gt;

&lt;ul class=&quot;time-vertical&quot; style=&quot;margin-left: 32px;&quot;&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;&quot;&gt;如何让二维坐标按照x轴优先的顺序从小到大排序？&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/count-sorted-vowel-strings/&quot;&gt;LeetCode Problem 1641. Count Sorted Vowel Strings&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/wiggle-sort-ii/&quot;&gt;LeetCode Problem 324. Wiggle Sort II&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/sort-array-by-parity-ii/&quot;&gt;LeetCode Problem 922. Sort Array By Parity II&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;https://leetcode.com/problems/remove-duplicates-from-sorted-list-ii/&quot;&gt;LeetCode Problem 82. Remove Duplicates from Sorted List II&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=896&quot;&gt;USACO 2019 Jan Silver P3&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=787&quot;&gt;USACO 2018 Jan Silver P2&lt;/a&gt;&lt;/li&gt;
        &lt;li&gt;&lt;online&gt;&lt;/online&gt;&lt;a href=&quot;http://www.usaco.org/index.php?page=viewproblem2&amp;amp;cpid=786&quot;&gt;USACO 2019 Jan Silver P1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
				<pubDate>Tue, 09 Mar 2021 00:00:00 +0000</pubDate>
				<link>https://gwcs.xyz/2021/03/09/Sort-List.html</link>
				<guid isPermaLink="false">https://gwcs.xyz/2021/03/09/Sort-List.html</guid>
			</item>
		
	</channel>
</rss>