Skip to content

Commit 83c49dd

Browse files
committed
Site updated: 2025-03-08 11:12:03
1 parent 3dfe856 commit 83c49dd

4 files changed

Lines changed: 154 additions & 100 deletions

File tree

ComputerScience/笔记/洛谷 错题本/index.html

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<meta property="og:description" content="P1004 [NOIP 2000 提高组] 方格取数 #走两次dp 如果只走一次,这题是非常经典的DP。但是要走两次,就变得非常有难度。 首先,可以简单地推广:要走两次,dp就存四个下标: int[][][][] dp &#x3D; new int[N][N][N][N]; 我们只需要遍历所有可能,并且比较四种走法(同下、同右、一下一右),取最大值就可以了。 注意,一个数只能取一次,需要一个判断防止重复取">
2929
<meta property="og:locale" content="zh_CN">
3030
<meta property="article:published_time" content="2025-02-28T16:00:00.000Z">
31-
<meta property="article:modified_time" content="2025-03-02T04:25:25.511Z">
31+
<meta property="article:modified_time" content="2025-03-08T01:17:51.150Z">
3232
<meta property="article:author" content="SIMULEITE">
3333
<meta property="article:tag" content="笔记">
3434
<meta name="twitter:card" content="summary">
@@ -141,7 +141,7 @@
141141
<div class="sidebar-panel-container">
142142
<!--noindex-->
143143
<div class="post-toc-wrap sidebar-panel">
144-
<div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#p1004-noip-2000-%E6%8F%90%E9%AB%98%E7%BB%84-%E6%96%B9%E6%A0%BC%E5%8F%96%E6%95%B0"><span class="nav-text"> P1004 [NOIP 2000 提高组] 方格取数</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#b3637-%E6%9C%80%E9%95%BF%E4%B8%8A%E5%8D%87%E5%AD%90%E5%BA%8F%E5%88%97"><span class="nav-text"> B3637 最长上升子序列</span></a></li></ol></div>
144+
<div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#p1004-noip-2000-%E6%8F%90%E9%AB%98%E7%BB%84-%E6%96%B9%E6%A0%BC%E5%8F%96%E6%95%B0"><span class="nav-text"> P1004 [NOIP 2000 提高组] 方格取数</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#b3637-%E6%9C%80%E9%95%BF%E4%B8%8A%E5%8D%87%E5%AD%90%E5%BA%8F%E5%88%97"><span class="nav-text"> B3637 最长上升子序列</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#p2782-%E5%8F%8B%E5%A5%BD%E5%9F%8E%E5%B8%82"><span class="nav-text"> P2782 友好城市</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B4%AA%E5%BF%83%E6%B3%95%E6%B1%82%E8%A7%A3lis"><span class="nav-text"> 贪心法求解LIS</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BC%98%E5%8C%96dp%E6%80%9D%E8%B7%AF%E4%BA%A4%E6%8D%A2%E7%8A%B6%E6%80%81%E4%B8%8E%E7%8A%B6%E6%80%81%E5%80%BC"><span class="nav-text"> 优化DP思路:交换状态与状态值</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#p1091-noip-2004-%E6%8F%90%E9%AB%98%E7%BB%84-%E5%90%88%E5%94%B1%E9%98%9F%E5%BD%A2"><span class="nav-text"> P1091 [NOIP 2004 提高组] 合唱队形</span></a></li></ol></div>
145145
</div>
146146
<!--/noindex-->
147147

@@ -223,7 +223,7 @@ <h1 class="post-title" itemprop="name headline">
223223
<i class="far fa-calendar-check"></i>
224224
</span>
225225
<span class="post-meta-item-text">更新于</span>
226-
<time title="修改时间:2025-03-02 12:25:25" itemprop="dateModified" datetime="2025-03-02T12:25:25+08:00">2025-03-02</time>
226+
<time title="修改时间:2025-03-08 09:17:51" itemprop="dateModified" datetime="2025-03-08T09:17:51+08:00">2025-03-08</time>
227227
</span>
228228

229229

@@ -252,7 +252,25 @@ <h1 id="b3637-最长上升子序列"><a class="markdownIt-Anchor" href="#b3637-
252252
<p>如何理解<code>dp[i] = Math.max(dp[i], dp[j] + 1)</code>?<br />
253253
这里dp[j]存储的是以j为结尾的LIS,而+1代表的是dp[i]自己。<br />
254254
我们通过计算出前面的所有dp[j],最后只需要看对于每个nums[j],它是否小于nums[i],小于,就添加一个就可以了。</p>
255-
255+
<h1 id="p2782-友好城市"><a class="markdownIt-Anchor" href="#p2782-友好城市"></a> P2782 友好城市</h1>
256+
<p>#贪心 #LIS最优解法<br />
257+
友好城市可以转换为一个LIS问题:将北岸城市按照坐标顺序排序后,求北岸城市对应南岸城市的坐标LIS(南岸城市坐标必须递增,不递增就是交叉造桥),这就是不交叉情况下能够建筑的最多桥梁数。<br />
258+
传统的DP写法需要<span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n^2)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.064108em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathdefault">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141079999999999em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>的时间复杂度,会超时;下面介绍LIS的最优解法:贪心+二分。</p>
259+
<h2 id="贪心法求解lis"><a class="markdownIt-Anchor" href="#贪心法求解lis"></a> 贪心法求解LIS</h2>
260+
<p>对于一个序列sequence,遍历sequence[i],维护一个上升序列数组,使其每个元素尽可能地小(这样整个序列就尽可能长),遍历结束,这个数组就是LIS。<br />
261+
具体的算法实现是:对于每个sequence[i],查找它在贪心上升序列greedy中应该插入的位置(维持序列上升的位置),并替换原来的更大的元素,如果不存在更大的元素,在末尾追加该元素。最后,greedy就是LIS,greedy的长度就是能够建筑合法桥梁的最大值。</p>
262+
<h3 id="优化dp思路交换状态与状态值"><a class="markdownIt-Anchor" href="#优化dp思路交换状态与状态值"></a> 优化DP思路:交换状态与状态值</h3>
263+
<p>原来的DP是这样表示:<br />
264+
<span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mtext> </mtext><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mtext> </mtext><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mtext> </mtext><mi mathvariant="normal"></mi><mi>c</mi><mi>i</mi><mi>t</mi><mi>i</mi><mi>e</mi><mi>s</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mi>L</mi><mi>I</mi><mi>S</mi><mtext> </mtext><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi></mrow><annotation encoding="application/x-tex">dp[i]\ 表示\ 末尾元素\ 为cities[i]的元素的LIS\ 长度</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault">d</span><span class="mord mathdefault">p</span><span class="mopen">[</span><span class="mord mathdefault">i</span><span class="mclose">]</span><span class="mspace"> </span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mspace"> </span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mspace"> </span><span class="mord cjk_fallback"></span><span class="mord mathdefault">c</span><span class="mord mathdefault">i</span><span class="mord mathdefault">t</span><span class="mord mathdefault">i</span><span class="mord mathdefault">e</span><span class="mord mathdefault">s</span><span class="mopen">[</span><span class="mord mathdefault">i</span><span class="mclose">]</span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mord mathdefault">L</span><span class="mord mathdefault" style="margin-right:0.07847em;">I</span><span class="mord mathdefault" style="margin-right:0.05764em;">S</span><span class="mspace"> </span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span></span></span></span><br />
265+
交换“末尾元素”与“长度”后:<br />
266+
<span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>g</mi><mi>r</mi><mi>e</mi><mi>e</mi><mi>d</mi><mi>y</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mtext> </mtext><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mtext> </mtext><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mtext> </mtext><mi mathvariant="normal"></mi><mi>i</mi><mo>+</mo><mn>1</mn><mi mathvariant="normal"></mi><mi>I</mi><mi>S</mi><mi mathvariant="normal"></mi><mtext> </mtext><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mtext> </mtext><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi><mi mathvariant="normal"></mi></mrow><annotation encoding="application/x-tex">greedy[i]\ 表示\ 长度\ 为i+1的IS的\ 末尾元素\ 的最小值</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.03588em;">g</span><span class="mord mathdefault" style="margin-right:0.02778em;">r</span><span class="mord mathdefault">e</span><span class="mord mathdefault">e</span><span class="mord mathdefault">d</span><span class="mord mathdefault" style="margin-right:0.03588em;">y</span><span class="mopen">[</span><span class="mord mathdefault">i</span><span class="mclose">]</span><span class="mspace"> </span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mspace"> </span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mspace"> </span><span class="mord cjk_fallback"></span><span class="mord mathdefault">i</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord">1</span><span class="mord cjk_fallback"></span><span class="mord mathdefault" style="margin-right:0.07847em;">I</span><span class="mord mathdefault" style="margin-right:0.05764em;">S</span><span class="mord cjk_fallback"></span><span class="mspace"> </span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mspace"> </span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span><span class="mord cjk_fallback"></span></span></span></span></p>
267+
<p>代码实现如下:</p>
268+
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line"> ... <span class="comment">// 处理输入,按北岸城市坐标cities[i].source排序</span></span><br><span class="line"> </span><br><span class="line"> <span class="type">int</span>[] greedy = <span class="keyword">new</span> <span class="title class_">int</span>[N];</span><br><span class="line"> <span class="type">int</span> <span class="variable">len</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; N; i += <span class="number">1</span>) &#123; <span class="comment">// 顺序遍历排好序的北岸城市坐标</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">target</span> <span class="operator">=</span> cities[i].target; <span class="comment">// 北岸城市对应的友好城市坐标</span></span><br><span class="line"> <span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> lowerBound(greedy, len-<span class="number">1</span>, target); <span class="comment">// 注意要传入len-1</span></span><br><span class="line"> <span class="keyword">if</span> (index == len) &#123; <span class="comment">// 追加元素</span></span><br><span class="line"> greedy[len++] = target;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123; <span class="comment">// 找到递增序列位置,替换</span></span><br><span class="line"> greedy[index] = target;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> System.out.println(len);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 寻找target应该插入到递增序列nums的下标位置</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">lowerBound</span><span class="params">(<span class="type">int</span>[] nums, <span class="type">int</span> end, <span class="type">int</span> target)</span> &#123;</span><br><span class="line"> <span class="type">int</span> <span class="variable">start</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (start &lt;= end) &#123;</span><br><span class="line"> <span class="type">int</span> <span class="variable">mid</span> <span class="operator">=</span> start + (end - start) / <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">if</span> (nums[mid] &gt;= target) &#123;</span><br><span class="line"> end = mid - <span class="number">1</span>;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> start = mid + <span class="number">1</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> start;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
269+
<h1 id="p1091-noip-2004-提高组-合唱队形"><a class="markdownIt-Anchor" href="#p1091-noip-2004-提高组-合唱队形"></a> P1091 [NOIP 2004 提高组] 合唱队形</h1>
270+
<p>#双向LIS<br />
271+
合唱队形可以看成求两边LIS之和的最大值。此时总人数减去LIS之和的最大值,就是最少出列队员数。<br />
272+
这里要注意当前index+1的值才是正确的长度。len标记的是数组的总长度,但是index会动态更新寻找更小值并做替换。当index找到最小值时,后面的更大值是在index以前的,不属于当前下标i+1结尾的IS长度。</p>
273+
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="type">int</span>[] gdUp = <span class="keyword">new</span> <span class="title class_">int</span>[N];</span><br><span class="line"><span class="type">int</span> <span class="variable">lenUp</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"><span class="type">int</span>[] lenUps = <span class="keyword">new</span> <span class="title class_">int</span>[N];</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; N; i += <span class="number">1</span>) &#123;</span><br><span class="line"> <span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> lowerBound(gdUp, lenUp-<span class="number">1</span>, members[i]);</span><br><span class="line"> <span class="keyword">if</span> (index == lenUp) &#123;</span><br><span class="line"> gdUp[lenUp++] = members[i];</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> gdUp[index] = members[i];</span><br><span class="line"> &#125;</span><br><span class="line"> lenUps[i] = index + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span>[] gdDown = <span class="keyword">new</span> <span class="title class_">int</span>[N];</span><br><span class="line"><span class="type">int</span> <span class="variable">lenDown</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"><span class="type">int</span>[] lenDowns = <span class="keyword">new</span> <span class="title class_">int</span>[N];</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> N-<span class="number">1</span>; i &gt;= <span class="number">0</span>; i -= <span class="number">1</span>) &#123;</span><br><span class="line"> <span class="type">int</span> <span class="variable">index</span> <span class="operator">=</span> lowerBound(gdDown, lenDown-<span class="number">1</span>, members[i]);</span><br><span class="line"> <span class="keyword">if</span> (index == lenDown) &#123;</span><br><span class="line"> gdDown[lenDown++] = members[i];</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> gdDown[index] = members[i];</span><br><span class="line"> &#125;</span><br><span class="line"> lenDowns[i] = index + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="variable">max</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; N; i += <span class="number">1</span>) &#123;</span><br><span class="line"> <span class="keyword">if</span> (lenUps[i] + lenDowns[i] - <span class="number">1</span> &gt; max) &#123;</span><br><span class="line"> max = lenUps[i] + lenDowns[i] - <span class="number">1</span>;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">System.out.println(N - max);</span><br></pre></td></tr></table></figure>
256274
</div>
257275

258276

0 commit comments

Comments
 (0)