<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Asahi 的博客</title>
  
  
  <link href="https://akioi.dev/atom.xml" rel="self"/>
  
  <link href="https://akioi.dev/"/>
  <updated>2026-08-21T15:32:11.612Z</updated>
  <id>https://akioi.dev/</id>
  
  <author>
    <name>odt03</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>题解 P12703 [KOI 2022 Round 2] 外环路</title>
    <link href="https://akioi.dev/2026/07/22/p12703-koi-2022-round-2/"/>
    <id>https://akioi.dev/2026/07/22/p12703-koi-2022-round-2/</id>
    <published>2026-07-22T00:31:18.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>一道练习点分治的题。</p><p>对于每一个点进行一遍 Dijkstra 是不可接受的，考虑点分治处理。</p><p>我们按照点分治的方式递归处理一个询问，假设当前递归到的分治中心是 $c$，询问的两点是 $u,v$，那么我们就要为最短路径分类。所有的最短路径可以分为三类：</p><ul><li>$\text{(A).}$ $z$ 的最短路经过 $c$。以分治中心 $c$ 为起点跑 Dijkstra，计算到 $c$ 到分治连通块内所有节点的最短路，那么此时 $d(u,v)&#x3D;d(c,u)+d(c,v)$。</li><li>$\text{(B).}$ $u,v$ 在分治连通块的不同子树内且最短路不经过 $c$。这是最短路必定经过外环边，若子树个数为 $s$，外环边最多有 $s$ 条，对于每一条边，我们任取其一端点 $p$ ，计算 $p$ 到分治连通块内所有节点的最短路，那么此时有</li></ul><p>$$d(u,v)&#x3D;\min_{i&#x3D;1}^{s}\left(d(p_i,u)+d(p_i,v)\right)$$</p><ul><li>$\text{(C).}$ $u,v$ 在分治连通块的同一子树内且最短路不经过 $c$。若最短路经过外环边，问题 $\text{(B)}$ 就可以解决。否则我们对这个子树进行递归分治处理。</li></ul><p>但是时间瓶颈是由子树个数 $s$ 决定的，因为我们对每一个分治重心都要跑 $s+1$ 遍 Dijkstra。根据题目条件，容易想到对整棵树进行三度化。此时对每一个分治重心只需最多跑 $4$ 遍 Dijkstra，而三度化最多只会新增 $n$ 个节点，所以总结点数仍是 $O(n)$ 的。</p><p>实际上分治时可以将所有询问离散化，在每次分治时一并处理，可以省很多空间。在递归时如果某个子树没有询问了，就不要向下递归，这样剪枝可以节省很多时间。</p><p>时间复杂度 $O(n\log^2n)$。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">const</span> <span class="type">int</span> inf = <span class="number">0x3f3f3f3f3f3f3f3fll</span>;</span><br><span class="line"><span class="type">int</span> n, k, Q, m;</span><br><span class="line">vector&lt;pair&lt;<span class="type">int</span>, <span class="type">int</span>&gt;&gt; G[<span class="number">200010</span>];</span><br><span class="line">vector&lt;<span class="type">int</span>&gt; T[<span class="number">200010</span>], outp;</span><br><span class="line"><span class="type">int</span> w[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Q</span> &#123;</span><br><span class="line">    <span class="type">int</span> u, v;</span><br><span class="line">&#125; q[<span class="number">250010</span>];</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">trans</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    m = n;</span><br><span class="line">    queue&lt;<span class="type">int</span>&gt; q; q.<span class="built_in">push</span>(<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">while</span> (!q.<span class="built_in">empty</span>()) &#123;</span><br><span class="line">        <span class="type">int</span> u = q.<span class="built_in">front</span>(); q.<span class="built_in">pop</span>();</span><br><span class="line">        <span class="keyword">while</span> (T[u].<span class="built_in">size</span>() &gt; <span class="number">2</span>) &#123;</span><br><span class="line">            <span class="type">int</span> x = T[u].<span class="built_in">back</span>(); T[u].<span class="built_in">pop_back</span>();</span><br><span class="line">            <span class="type">int</span> y = T[u].<span class="built_in">back</span>(); T[u].<span class="built_in">pop_back</span>();</span><br><span class="line">            <span class="type">int</span> dx = G[u].<span class="built_in">back</span>().second; G[u].<span class="built_in">pop_back</span>();</span><br><span class="line">            <span class="type">int</span> dy = G[u].<span class="built_in">back</span>().second; G[u].<span class="built_in">pop_back</span>();</span><br><span class="line">            m++;</span><br><span class="line">            T[m].<span class="built_in">push_back</span>(x), T[m].<span class="built_in">push_back</span>(y);</span><br><span class="line">            G[m].<span class="built_in">push_back</span>(&#123;x, dx&#125;), G[m].<span class="built_in">push_back</span>(&#123;y, dy&#125;);</span><br><span class="line">            T[u].<span class="built_in">push_back</span>(m); G[u].<span class="built_in">push_back</span>(&#123;m, <span class="number">0</span>&#125;);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> v : T[u]) q.<span class="built_in">push</span>(v);</span><br><span class="line">    &#125;</span><br><span class="line">    vector&lt;tuple&lt;<span class="type">int</span>, <span class="type">int</span>, <span class="type">int</span>&gt;&gt; t;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> u = <span class="number">1</span>; u &lt;= m; u++)</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">auto</span> &amp;[v, d] : G[u]) t.<span class="built_in">push_back</span>(&#123;u, v, d&#125;);</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> &amp;[u, v, d] : t) T[v].<span class="built_in">push_back</span>(u), G[v].<span class="built_in">push_back</span>(&#123;u, d&#125;); </span><br><span class="line">&#125;</span><br><span class="line">vector&lt;<span class="type">int</span>&gt; all, todo;</span><br><span class="line"><span class="type">bool</span> vis[<span class="number">200010</span>];</span><br><span class="line"><span class="type">int</span> siz[<span class="number">200010</span>], bid[<span class="number">200010</span>];</span><br><span class="line"><span class="type">int</span> dis[<span class="number">200010</span>];</span><br><span class="line"><span class="type">int</span> ans[<span class="number">250010</span>];</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">getsz</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa)</span> </span>&#123;</span><br><span class="line">    siz[u] = <span class="number">1</span>; all.<span class="built_in">push_back</span>(u);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> v : T[u]) &#123;</span><br><span class="line">        <span class="keyword">if</span> (v == fa || vis[v]) <span class="keyword">continue</span>;</span><br><span class="line">        <span class="built_in">getsz</span>(v, u);</span><br><span class="line">        siz[u] += siz[v];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">getrt</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa, <span class="type">int</span> sz)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> v : T[u]) &#123;</span><br><span class="line">        <span class="keyword">if</span> (v == fa || vis[v]) <span class="keyword">continue</span>;</span><br><span class="line">        <span class="keyword">if</span> (siz[v] &gt; sz / <span class="number">2</span>) <span class="keyword">return</span> <span class="built_in">getrt</span>(v, u, sz);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> u;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">fill</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa, <span class="type">int</span> id)</span> </span>&#123;</span><br><span class="line">    bid[u] = id;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> v : T[u]) &#123;</span><br><span class="line">        <span class="keyword">if</span> (v == fa || vis[v]) <span class="keyword">continue</span>;</span><br><span class="line">        <span class="built_in">fill</span>(v, u, id);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dij</span><span class="params">(<span class="type">int</span> s, vector&lt;<span class="type">int</span>&gt; &amp;em)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> u : em) dis[u] = inf;</span><br><span class="line">    priority_queue&lt;pair&lt;<span class="type">int</span>, <span class="type">int</span>&gt;&gt; pq;</span><br><span class="line">    dis[s] = <span class="number">0</span>; pq.<span class="built_in">push</span>(&#123;<span class="number">0</span>, s&#125;);</span><br><span class="line">    <span class="keyword">while</span> (!pq.<span class="built_in">empty</span>()) &#123;</span><br><span class="line">        <span class="keyword">auto</span> [d, u] = pq.<span class="built_in">top</span>(); pq.<span class="built_in">pop</span>();</span><br><span class="line">        d = -d;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">auto</span> [v, ds] : G[u]) &#123;</span><br><span class="line">            <span class="keyword">if</span> (!bid[v] || d + ds &gt;= dis[v]) <span class="keyword">continue</span>;</span><br><span class="line">            dis[v] = d + ds;</span><br><span class="line">            pq.<span class="built_in">push</span>(&#123;-dis[v], v&#125;);   </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">find</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> [v, ds] : G[u])</span><br><span class="line">        <span class="keyword">if</span> (bid[u] &gt; <span class="number">0</span> &amp;&amp; bid[v] &gt; <span class="number">0</span> &amp;&amp; bid[u] &lt; bid[v]) todo.<span class="built_in">push_back</span>(u);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> v : T[u]) &#123;</span><br><span class="line">        <span class="keyword">if</span> (v == fa || vis[v]) <span class="keyword">continue</span>;</span><br><span class="line">        <span class="built_in">find</span>(v, u);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">work</span><span class="params">(<span class="type">int</span> u, vector&lt;<span class="type">int</span>&gt; &amp;que)</span> </span>&#123;</span><br><span class="line">    <span class="built_in">getsz</span>(u, <span class="number">0</span>);</span><br><span class="line">    <span class="type">int</span> rt = <span class="built_in">getrt</span>(u, <span class="number">0</span>, siz[u]);</span><br><span class="line">    vis[rt] = <span class="number">1</span>;</span><br><span class="line">    <span class="type">int</span> tid = <span class="number">0</span>;</span><br><span class="line">    <span class="type">int</span> pson[<span class="number">4</span>] = &#123;<span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>&#125;;</span><br><span class="line">    bid[rt] = <span class="number">-1</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> son : T[rt]) &#123;</span><br><span class="line">        <span class="keyword">if</span> (vis[son]) <span class="keyword">continue</span>;</span><br><span class="line">        <span class="built_in">fill</span>(son, rt, ++tid);</span><br><span class="line">        pson[tid] = son;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> son : T[rt]) &#123;</span><br><span class="line">        <span class="keyword">if</span> (vis[son]) <span class="keyword">continue</span>;</span><br><span class="line">        <span class="built_in">find</span>(son, rt);</span><br><span class="line">    &#125;</span><br><span class="line">    todo.<span class="built_in">push_back</span>(rt);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> now : todo) &#123;</span><br><span class="line">        <span class="built_in">dij</span>(now, all);</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> id : que) &#123;</span><br><span class="line">            <span class="type">int</span> qu = q[id].u, qv = q[id].v;</span><br><span class="line">            ans[id] = <span class="built_in">min</span>(ans[id], dis[qu] + dis[qv]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    vector&lt;<span class="type">int</span>&gt; subq[<span class="number">4</span>];</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> id : que) &#123;</span><br><span class="line">        <span class="type">int</span> qu = q[id].u, qv = q[id].v;</span><br><span class="line">        <span class="keyword">if</span> (bid[qu] == bid[qv]) subq[bid[qu]].<span class="built_in">push_back</span>(id);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> u : all) bid[u] = <span class="number">0</span>;</span><br><span class="line">    all.<span class="built_in">clear</span>(); todo.<span class="built_in">clear</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= tid; i++) </span><br><span class="line">        <span class="keyword">if</span> (!subq[i].<span class="built_in">empty</span>()) <span class="built_in">work</span>(pson[i], subq[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    n = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">2</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        <span class="type">int</span> p = <span class="built_in">read</span>(), d = <span class="built_in">read</span>();</span><br><span class="line">        G[p].<span class="built_in">push_back</span>(&#123;i, d&#125;);</span><br><span class="line">        T[p].<span class="built_in">push_back</span>(i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) <span class="keyword">if</span> (T[i].<span class="built_in">empty</span>()) k++, outp.<span class="built_in">push_back</span>(i);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++) w[i] = <span class="built_in">read</span>();</span><br><span class="line">    Q = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= Q; i++) q[i].u = <span class="built_in">read</span>(), q[i].v = <span class="built_in">read</span>();</span><br><span class="line">    <span class="built_in">trans</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; k; i++) &#123;</span><br><span class="line">        <span class="type">int</span> u = outp[i], v = outp[(i + <span class="number">1</span>) % k];</span><br><span class="line">        G[u].<span class="built_in">push_back</span>(&#123;v, w[i + <span class="number">1</span>]&#125;);</span><br><span class="line">        G[v].<span class="built_in">push_back</span>(&#123;u, w[i + <span class="number">1</span>]&#125;);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= Q; i++) ans[i] = inf;</span><br><span class="line">    vector&lt;<span class="type">int</span>&gt; que;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= Q; i++) que.<span class="built_in">push_back</span>(i);</span><br><span class="line">    <span class="built_in">work</span>(<span class="number">1</span>, que);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= Q; i++) <span class="built_in">printf</span>(<span class="string">&quot;%lld\n&quot;</span>, ans[i]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;一道练习点分治的题。&lt;/p&gt;
&lt;p&gt;对于每一个点进行一遍 Dijkstra 是不可接受的，考虑点分治处理。&lt;/p&gt;
&lt;p&gt;我们按照点分治的方式递归处理一个询问，假设当前递归到的分治中心是 $c$，询问的两点是 $u,v$，那么我们就要为最短路径分类。所有的最短路径可以分为三</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="点分治" scheme="https://akioi.dev/tags/%E7%82%B9%E5%88%86%E6%B2%BB/"/>
    
    <category term="最短路" scheme="https://akioi.dev/tags/%E6%9C%80%E7%9F%AD%E8%B7%AF/"/>
    
    <category term="Dijkstra" scheme="https://akioi.dev/tags/Dijkstra/"/>
    
  </entry>
  
  <entry>
    <title>题解 CF2103D Local Construction</title>
    <link href="https://akioi.dev/2026/04/08/cf2103d-local-construction/"/>
    <id>https://akioi.dev/2026/04/08/cf2103d-local-construction/</id>
    <published>2026-04-08T08:59:26.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>根据每个数被删除的轮次，我们可以得知或构造出数之间大小关系的约束。若有向边 $u\to v$ 表示 $u&gt;v$，那么最终构成的约束图一定是 DAG，按照这幅图的拓扑序由 $n$ 向 $1$ 分配数的大小便是一组合法解。</p><p>考虑构造约束图。当前进行到第 $i$ 轮，当前还未被淘汰掉的点有 $u_1,u_2,\dots,u_k$，这里考虑进行到偶数轮，奇数轮是这种情况的对称。如果点 $u_i$ 在当前论中没被淘汰，那么一定有 $u_i&gt;u_{i-1}$ 且 $u_i&gt;u_{i+1}$，所以连接 $u_i\to u_{i-1}$ 和 $u_i\to u_{i+1}$。如果点 $u_i$ 在当前论中被淘汰了，若其左右没被淘汰，那么大小关系一定是确定的，不用考虑。如果有一个连通块 $u_l,u_{l+1}，\dots,u_r$，所有的点在这一轮中都是要淘汰的，那么就需要手动确定一组大小关系来满足条件，连通块内的点只能全部用 $&lt;$ 或 $&gt;$ 连接。若 $u_l&#x3D;u_1$，那么只能有 $u_l&lt;u_{l+1}&lt;\dots&lt;u_r$，否则若 $u_1&gt;u_2$ 时 $u_1$ 就不会被淘汰了。同理，若 $u_r&#x3D;u_k$，那么只能有 $u_l&gt;u_{l+1}&gt;\dots&gt;u_r$。一般情况下 $u_l&lt;u_{l+1}&lt;\dots&lt;u_r$ 和 $u_l&gt;u_{l+1}&gt;\dots&gt;u_r$ 都是可行的，随便选择一组连接即可。</p><p>时间复杂度 $O(n)$。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;根据每个数被删除的轮次，我们可以得知或构造出数之间大小关系的约束。若有向边 $u&#92;to v$ 表示 $u&amp;gt;v$，那么最终构成的约束图一定是 DAG，按照这幅图的拓扑序由 $n$ 向 $1$ 分配数的大小便是一组合法解。&lt;/p&gt;
&lt;p&gt;考虑构造约束图。当前进行到第 $i</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="构造" scheme="https://akioi.dev/tags/%E6%9E%84%E9%80%A0/"/>
    
    <category term="拓扑排序" scheme="https://akioi.dev/tags/%E6%8B%93%E6%89%91%E6%8E%92%E5%BA%8F/"/>
    
    <category term="图论" scheme="https://akioi.dev/tags/%E5%9B%BE%E8%AE%BA/"/>
    
  </entry>
  
  <entry>
    <title>题解 P8194 [USACO22FEB] Phone Numbers P</title>
    <link href="https://akioi.dev/2026/03/20/p8194-usaco22feb-phone-numbers/"/>
    <id>https://akioi.dev/2026/03/20/p8194-usaco22feb-phone-numbers/</id>
    <published>2026-03-20T09:01:01.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>感觉这是一个很聪明的 DP 套 DP 啊。</p><p>首先我们考虑有一个确定的序列 $X$，其是否能与序列 $A$ 通过一样的按法按出来的 DP 怎么做？定义两个序列能通过一样的按法为两个序列是否<strong>匹配</strong>，那么我们用 $f_i$ 表示 $A$ 与 $X$ 的前 $i$ 项是否匹配，转移很简单，我们判断最后 $1&#x2F;2&#x2F;4$ 位是否能匹配，与之前的答案相拼即可。</p><p>下面考虑设计状态。一个数的匹配状态显然最多只和前面三个数是什么有关，所以我们定义 $F_{i,a,b,c,p_1,p_2,p_3,p_4}$ 表示倒数的三个数分别是 $a,b,c$ 且倒数的四个位置的 $f$ 值分别是 $p_1,p_2,p_3,p_4$ 的方案数。对于 $F_i$ 来说，我们枚举第 $i+1$ 个数是什么，并判断 $[i-2,i+1]$ 或 $[i,i+1]$ 或 $i+1$ 这几个区间能否匹配且前面的那一部分是否匹配来决定新的 $p_4$ 的值。这样转移我们考虑的是每一个新数的值是什么，显然这样计数是不重不漏的。</p><p>具体地，转移显然是由 $F_{i,a,b,c,p_1,p_2,p_3,p_4}$ 向 $F_{i+1,b,c,d,p_2,p_3,p_4,p^{\prime}}$ 的。显然有下式：$$F_{i,a,b,c,p_1,p_2,p_3,p_4}\rightarrow F_{i+1,b,c,d,p_2,p_3,p_4,p^{\prime}}$$$p^{\prime}&#x3D;1$ 成立条件如下：$$p^{\prime} &#x3D; 1 \iff\begin{aligned}&amp; [i-2,i+1]\text{ is valid } \land p_1&#x3D;1 &amp; \text{(1)} \\\lor\ &amp; [i,i+1]\text{ is valid } \land p_3&#x3D;1 &amp; \text{(2)} \\\lor\ &amp; d&#x3D;a_{i+1} \land p_4&#x3D;1 &amp; \text{(3)}\end{aligned}$$$[L,R]\text{ is valid}$ 表示区间 $[L,R]$ 是否能与 $A$ 序列相应区间匹配。</p><p>这样 DP 的状态时间复杂度为 $O(n)$，但是对于每一个 $i$ 来说，枚举状态有 $9^3\times2^4$ 种，转移时要枚举 $9$ 个数。这样常数太大（比 $n$ 都大了），考虑减少状态数。</p><p>其实在 $9^3\times2^4$ 种状态中，有很多状态向后转移的效果是一样的，所以我们可以合并且少枚举一些状态，这样会大大减少转移常数。考虑决定 $p^{\prime}$ 的三个条件：$$\begin{aligned}&amp; [i-2,i+1]\text{ is valid } \land p_1&#x3D;1 &amp; \text{(1)} \\&amp; [i,i+1]\text{ is valid } \land p_3&#x3D;1 &amp; \text{(2)} \\&amp; d&#x3D;a_{i+1} \land p_4&#x3D;1 &amp; \text{(3)}\end{aligned}$$先从 $p$ 的角度考虑。如果 $p_1&#x3D;0$，此时条件 $(1)$ 肯定不能满足了，那么无论 $a$ 是多少，向后转移的结果都是一样的，所以不用记录 $a$ 了。如果 $p_1&#x3D;p_2&#x3D;0$，那么最早为 $1$ 的位置是 $p_3$，这是只有条件 $(2)$ 和 $(3)$ 能被满足，同理 $b$ 也没有记录的必要了。如果 $p_1&#x3D;p_2&#x3D;p_3&#x3D;0$，那么只有条件 $(3)$ 有满足的可能，$c$ 也没有记录的必要了。然后从区间匹配的角度去考虑。如果 $(a,b,c)$ 与任意的 $d$ 都不能匹配，$p_1$ 和 $a$ 就没有记录的必要了。同理，如果 $(b,c)$ 与任意的 $(d,e)$ 都不能匹配，同理 $p_2$ 和 $b$ 也就没有记录的必要了。这样状态最多只有 $150$ 种左右，足够通过此题。</p><p>在实现代码时，我们可以用<code>unordered_map</code>存储每一个状态，对于每一个 $i$，枚举 $i+1$ 那一位的值并判断新的 $p_4$ 是否合法来写出新的状态，再对其进行剪枝处理合并状态。注意到 $F_i$ 只会转移到 $F_{i+1}$，所以我们使用滚动数组存储 $F_i$，这样大大减少了使用的空间。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;感觉这是一个很聪明的 DP 套 DP 啊。&lt;/p&gt;
&lt;p&gt;首先我们考虑有一个确定的序列 $X$，其是否能与序列 $A$ 通过一样的按法按出来的 DP 怎么做？定义两个序列能通过一样的按法为两个序列是否&lt;strong&gt;匹配&lt;/strong&gt;，那么我们用 $f_i$ 表示 $A</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="动态规划" scheme="https://akioi.dev/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
    
    <category term="状态压缩" scheme="https://akioi.dev/tags/%E7%8A%B6%E6%80%81%E5%8E%8B%E7%BC%A9/"/>
    
  </entry>
  
  <entry>
    <title>题解 P15301 [ROI 2012 Day 2] army 汗国军队</title>
    <link href="https://akioi.dev/2026/03/18/p15301-roi-2012-day-2-army/"/>
    <id>https://akioi.dev/2026/03/18/p15301-roi-2012-day-2-army/</id>
    <published>2026-03-18T12:17:15.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>感觉这个题的状态定义挺有 LIS 的套路的。感觉这个题可以用<a href="https://www.luogu.com.cn/problem/P4484">最长上升子序列</a>的那种方法去定义状态去做，但是我用了另一种转化方式。</p><p>相对于普通的 LIS 计数，我们不仅需要考虑 LIS 的长度，还需要让护卫的编号（以下定义为“关键数字”）在原序列中单调递增地出现。如何根据这两个限制来定义状态呢？</p><p>有一种求 LIS 的方式：定义一个集合 $S$，初始时 $S&#x3D;\varnothing$，对于每一个 $a_i$，如果 $S$ 中存在最小的 $x$ 使得 $x&gt;a_i$，那么删去 $x$ 加入 $a_i$，否则直接加入 $a_i$，最终 $|S|$ 即为 LIS。</p><p>我们可以根据这种方式设计 dp 状态。定义 $dp_{S,T}$ 表示当前已经考虑了 $S$ 中的数，在集合中的数有 $T$，的方案数。这样定义状态数时我们可以用 $|T|$ 限制 LIS 的长度。在转移的时候，我们统计一下 $S$ 中出现了几个关键数字，在加入新的数字的时候判断一下是否是关键数字，如果是的话只能加入第一个没出现的，这样就能考虑到关键数字顺序的限制。</p><p>下面分析时间复杂度。由于 $T\subseteq S$，所以枚举状态时间复杂度是 $O(3^n)$ 的，转移的时候枚举新加入的数时间复杂度是 $O(n)$ 的，所以总时间复杂度为 $O(n3^n)$。在实现的时候用<code>unordered_map</code>存储子集状态就可以了，在实现时需稍微注意一下常数。</p><p>代码实现可以参考。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a[<span class="number">20</span>], sp[<span class="number">20</span>];</span><br><span class="line">unordered_map&lt;<span class="type">int</span>, ll&gt; dp[<span class="number">50010</span>];</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> n = <span class="built_in">read</span>(), k = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">if</span> (k == <span class="number">1</span>) &#123;cout &lt;&lt; <span class="number">1</span>; <span class="keyword">return</span>;&#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++) a[i] = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++) sp[a[i]] = i;</span><br><span class="line">    dp[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> b = <span class="number">0</span>; b &lt; (<span class="number">1</span> &lt;&lt; n); b++) &#123;</span><br><span class="line">        <span class="type">int</span> fst = k + <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++)</span><br><span class="line">            <span class="keyword">if</span> (!((b &gt;&gt; (a[i] - <span class="number">1</span>)) &amp; <span class="number">1</span>)) fst = <span class="built_in">min</span>(fst, i);</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">auto</span> &amp;it : dp[b]) &#123;</span><br><span class="line">            <span class="type">int</span> sb = it.first; ll val = it.second;</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">                <span class="keyword">if</span> ((b &gt;&gt; (i - <span class="number">1</span>)) &amp; <span class="number">1</span>) <span class="keyword">continue</span>;</span><br><span class="line">                <span class="keyword">if</span> (sp[i] &amp;&amp; i != a[fst]) <span class="keyword">continue</span>;</span><br><span class="line">                <span class="type">int</span> bit = <span class="number">1</span> &lt;&lt; (i - <span class="number">1</span>);</span><br><span class="line">                <span class="type">int</span> nb = b | bit, nsb = sb | bit;</span><br><span class="line">                <span class="type">int</span> tr = sb &amp; (~((<span class="number">1</span> &lt;&lt; i) - <span class="number">1</span>));</span><br><span class="line">                <span class="keyword">if</span> (tr) &#123;</span><br><span class="line">                    <span class="type">int</span> j = __builtin_ctz(tr) + <span class="number">1</span>;</span><br><span class="line">                    <span class="type">int</span> dl = (<span class="number">1</span> &lt;&lt; n) - <span class="number">1</span> - (<span class="number">1</span> &lt;&lt; (j - <span class="number">1</span>));</span><br><span class="line">                    nsb &amp;= dl;</span><br><span class="line">                &#125;</span><br><span class="line">                dp[nb][nsb] += val;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    ll ans = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> &amp;it : dp[(<span class="number">1</span> &lt;&lt; n) - <span class="number">1</span>])</span><br><span class="line">        <span class="keyword">if</span> (__builtin_popcount(it.first) == k) ans += it.second;</span><br><span class="line">    cout &lt;&lt; ans;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;感觉这个题的状态定义挺有 LIS 的套路的。感觉这个题可以用&lt;a href=&quot;https://www.luogu.com.cn/problem/P4484&quot;&gt;最长上升子序列&lt;/a&gt;的那种方法去定义状态去做，但是我用了另一种转化方式。&lt;/p&gt;
&lt;p&gt;相对于普通的 LIS 计数</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="动态规划" scheme="https://akioi.dev/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
    
    <category term="状态压缩" scheme="https://akioi.dev/tags/%E7%8A%B6%E6%80%81%E5%8E%8B%E7%BC%A9/"/>
    
    <category term="最长上升子序列" scheme="https://akioi.dev/tags/%E6%9C%80%E9%95%BF%E4%B8%8A%E5%8D%87%E5%AD%90%E5%BA%8F%E5%88%97/"/>
    
  </entry>
  
  <entry>
    <title>题解 [ABC447F] Centipede Graph</title>
    <link href="https://akioi.dev/2026/03/01/abc447f-centipede-graph/"/>
    <id>https://akioi.dev/2026/03/01/abc447f-centipede-graph/</id>
    <published>2026-03-01T01:46:44.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>一道简单的树形 dp 题。</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>由于题目让我们求在树的子图中最长的蜈蚣图的长度，所以容易想到要用树形 dp 解决。我们定义一个蜈蚣图的身体为其中间的链，腿为和中间链连接的两个点。对于一个身体上的点来说，腿与其有两种连接方式，一种是选取两个子节点作为腿，一种是选取一个子节点和父节点作为腿。设当前考虑的节点为 $u$，如果选择了 $fa_u$，那么蜈蚣的身体就不能再向 $fa_u$ 及其祖先转移。所以我们定义 $f_{u,0}$ 表示以 $u$ 为蜈蚣的身体上端点而且不选 $fa_u$ 最为腿的最大长度，而 $f_{u,1}$ 则是选 $fa_u$ 最为腿的最大长度。然而我们发现身体端点不一定所有身体节点的祖先，所以我们定义 $g_u$ 表示以 $u$ 为身体中点的最大长度。</p><p>下面我们考虑如何转移。</p><p>若 $v$ 是 $u$ 的儿子，我们定义最大的 $f_{v,0}$ 叫 $w_0$，次大的 $f_{v,0}$ 叫 $w_1$，其儿子个数为 $n_u$。那么有以下几种转移。$$f_{u,0}&#x3D;\max(f_{u,0},w_0+1),n_u\geq3$$</p><p>$$f_{u,1}&#x3D;\max(f_{u,1},w_0+1),n_u\geq2\land u\neq root$$</p><p>当然，如果 $u$ 作为蜈蚣的身体下端点的话，则有如下转移：$$f_{u,0}&#x3D;\max(f_{u,0},1),n_u\geq2$$</p><p>$$f_{u,1}&#x3D;\max(f_{u,1},1),n_u\geq1\land u\neq root$$</p><p>那么拼接两个蜈蚣的情况如下：$$g_u&#x3D;\max(g_u,w_0+w_1+1),n_u\geq4 \lor (n_u\geq3\land u\neq root)$$最后的答案如下：$$ans&#x3D;\max_{u&#x3D;1}^n\left(\max(f_{u,0},f_{u,1},g_u)\right)$$</p><p>时间复杂度 $O(n)$。</p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> n;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Node</span> &#123;</span><br><span class="line">    <span class="type">int</span> to, next;</span><br><span class="line">&#125; edge[<span class="number">400010</span>];</span><br><span class="line"><span class="type">int</span> head[<span class="number">200010</span>], tot;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">add</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> v)</span> </span>&#123;</span><br><span class="line">    edge[++tot].to = v;</span><br><span class="line">    edge[tot].next = head[u], head[u] = tot;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">int</span> dp[<span class="number">200010</span>][<span class="number">2</span>], Ans;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u, <span class="type">int</span> fa)</span> </span>&#123;</span><br><span class="line">    vector&lt;<span class="type">int</span>&gt; v0;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = head[u]; i; i = edge[i].next) &#123;</span><br><span class="line">        <span class="type">int</span> v = edge[i].to;</span><br><span class="line">        <span class="keyword">if</span> (v == fa) <span class="keyword">continue</span>;</span><br><span class="line">        <span class="built_in">dfs</span>(v, u);</span><br><span class="line">        v0.<span class="built_in">push_back</span>(dp[v][<span class="number">0</span>]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">sort</span>(v0.<span class="built_in">begin</span>(), v0.<span class="built_in">end</span>(), <span class="built_in">greater</span>&lt;<span class="type">int</span>&gt;());</span><br><span class="line">    <span class="keyword">if</span> (v0.<span class="built_in">size</span>() &gt;= <span class="number">3</span>) dp[u][<span class="number">0</span>] = <span class="built_in">max</span>(dp[u][<span class="number">0</span>], v0[<span class="number">0</span>] + <span class="number">1</span>);</span><br><span class="line">    <span class="keyword">if</span> (v0.<span class="built_in">size</span>() &gt;= <span class="number">2</span> &amp;&amp; u != <span class="number">1</span>) dp[u][<span class="number">1</span>] = <span class="built_in">max</span>(dp[u][<span class="number">1</span>], v0[<span class="number">0</span>] + <span class="number">1</span>);</span><br><span class="line">    <span class="keyword">if</span> (v0.<span class="built_in">size</span>() &gt;= <span class="number">2</span>) dp[u][<span class="number">0</span>] = <span class="built_in">max</span>(dp[u][<span class="number">0</span>], <span class="number">1</span>);</span><br><span class="line">    <span class="keyword">if</span> (v0.<span class="built_in">size</span>() &gt;= <span class="number">1</span> &amp;&amp; u != <span class="number">1</span>) dp[u][<span class="number">1</span>] = <span class="built_in">max</span>(dp[u][<span class="number">1</span>], <span class="number">1</span>);</span><br><span class="line">    Ans = <span class="built_in">max</span>(&#123;Ans, dp[u][<span class="number">0</span>], dp[u][<span class="number">1</span>]&#125;);</span><br><span class="line">    <span class="keyword">if</span> (v0.<span class="built_in">size</span>() &gt;= <span class="number">4</span>) Ans = <span class="built_in">max</span>(Ans, v0[<span class="number">0</span>] + v0[<span class="number">1</span>] + <span class="number">1</span>);</span><br><span class="line">    <span class="keyword">if</span> (v0.<span class="built_in">size</span>() &gt;= <span class="number">3</span> &amp;&amp; u != <span class="number">1</span>) Ans = <span class="built_in">max</span>(Ans, v0[<span class="number">0</span>] + v0[<span class="number">1</span>] + <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">init</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) head[i] = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= tot; i++) edge[i].to = edge[i].next = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) dp[i][<span class="number">0</span>] = dp[i][<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    Ans = <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    n = <span class="built_in">read</span>();</span><br><span class="line">    <span class="built_in">init</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt; n; i++) &#123;</span><br><span class="line">        <span class="type">int</span> u = <span class="built_in">read</span>(), v = <span class="built_in">read</span>();</span><br><span class="line">        <span class="built_in">add</span>(u, v), <span class="built_in">add</span>(v, u);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">dfs</span>(<span class="number">1</span>, <span class="number">-1</span>);</span><br><span class="line">    cout &lt;&lt; Ans &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;一道简单的树形 dp 题。&lt;/p&gt;
&lt;h2 id=&quot;思路&quot;&gt;&lt;a href=&quot;#思路&quot; class=&quot;headerlink&quot; title=&quot;思路&quot;&gt;&lt;/a&gt;思路&lt;/h2&gt;&lt;p&gt;由于题目让我们求在树的子图中最长的蜈蚣图的长度，所以容易想到要用树形 dp 解决。我们定义一个蜈蚣</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="树形 dp" scheme="https://akioi.dev/tags/%E6%A0%91%E5%BD%A2-dp/"/>
    
  </entry>
  
  <entry>
    <title>题解 CF1743E FTL</title>
    <link href="https://akioi.dev/2026/01/06/cf1743e-ftl/"/>
    <id>https://akioi.dev/2026/01/06/cf1743e-ftl/</id>
    <published>2026-01-06T03:10:26.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>其实只进行一次连发的 $f_i$ 不用去 dp，直接二分一下就行，这样会运行得更快。</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>我们容易注意到，每进行完一次连发之后，两个炮都要重新进入一轮冷却，相当于我们面对的是一个血量更少的敌人，这构成了一个新的子问题。我们只需要考虑在打掉怪物多少血量的时候连发，可以让总时间最小。这显然是一个 dp 问题，定义 $f_i$ 表示只能连发一次并且打掉 $i$ 的血量所需要的最小时间，$g_i$ 表示连发多次并且打掉 $i$ 的血量所需要的最小时间。容易得到 dp 方程如下：</p><p>$$g_i &#x3D; \min_{j &lt; i}\lbrace g_j + f _{i - j}\rbrace$$</p><p>对于 $f_i$ 我们二分枚举所需时间，这样更方便一些。</p><p>但是有一种情况，一个炮冷却时间特别长，所以连发不如单个打划算。我们在二分的时候把这种情况考虑一下就行。</p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> int long long</span></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> inf = <span class="number">0x3f3f3f3f3f3f3f3fll</span>;</span><br><span class="line"><span class="type">int</span> p1, p2, t1, t2, h, s;</span><br><span class="line"><span class="type">int</span> f[<span class="number">10010</span>], g[<span class="number">10010</span>];</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">chk</span><span class="params">(<span class="type">int</span> x)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (x &lt; t1 || x &lt; t2) <span class="keyword">return</span> x / t1 * (p1 - s) + x / t2 * (p2 - s);</span><br><span class="line">    <span class="type">int</span> ret = <span class="number">0</span>;</span><br><span class="line">    ret += p1 + p2 - s;</span><br><span class="line">    <span class="type">int</span> r1 = x - t1, r2 = x - t2;</span><br><span class="line">    ret += r1 / t1 * (p1 - s) + r2 / t2 * (p2 - s);</span><br><span class="line">    <span class="keyword">if</span> (ret &lt; <span class="number">0</span>) ret = inf;</span><br><span class="line">    <span class="keyword">return</span> ret;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    p1 = <span class="built_in">read</span>(), t1 = <span class="built_in">read</span>(), p2 = <span class="built_in">read</span>(), t2 = <span class="built_in">read</span>();</span><br><span class="line">    h = <span class="built_in">read</span>(), s = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= h; i++) &#123;</span><br><span class="line">        <span class="type">int</span> p = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = (<span class="number">1ll</span> &lt;&lt; <span class="number">60</span>); j; j &gt;&gt;= <span class="number">1</span>) </span><br><span class="line">            <span class="keyword">if</span> (<span class="built_in">chk</span>(p + j) &lt; i) p += j;</span><br><span class="line">        f[i] = p + <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">memset</span>(g, <span class="number">0x3f</span>, <span class="keyword">sizeof</span>(g));</span><br><span class="line">    g[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= h; i++) </span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j &lt; i; j++) </span><br><span class="line">            g[i] = <span class="built_in">min</span>(g[i], g[j] + f[i - j]);</span><br><span class="line">    cout &lt;&lt; g[h] &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;其实只进行一次连发的 $f_i$ 不用去 dp，直接二分一下就行，这样会运行得更快。&lt;/p&gt;
&lt;h2 id=&quot;思路&quot;&gt;&lt;a href=&quot;#思路&quot; class=&quot;headerlink&quot; title=&quot;思路&quot;&gt;&lt;/a&gt;思路&lt;/h2&gt;&lt;p&gt;我们容易注意到，每进行完一次连发之后，两</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="二分" scheme="https://akioi.dev/tags/%E4%BA%8C%E5%88%86/"/>
    
    <category term="动态规划" scheme="https://akioi.dev/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
    
  </entry>
  
  <entry>
    <title>题解：P13531 [OOI 2023] A task for substrings / 字符串问题</title>
    <link href="https://akioi.dev/2025/11/14/p13531-ooi-2023-a-task-for-substrings/"/>
    <id>https://akioi.dev/2025/11/14/p13531-ooi-2023-a-task-for-substrings/</id>
    <published>2025-11-14T09:16:32.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>看到字符串匹配，我们就要往 AC 自动机上去想。我们根据 AC 自动机的性质，我们很容易得知在第 $i$ 位结尾的匹配有多少个，所以我们可以很轻松地得到一个文本串的<strong>前缀</strong>的匹配数。</p><p>因此，我们考虑：假设第 $i$ 个位置的匹配数是 $suc_i$，那么我们能不能把区间 $[l, r]$ 的匹配数转化成 $suc_r - suc_l$ 这样的形式？大体可行，但是有一些情况我们需要处理。</p><p>我们询问的区间是 $[l, r]$，有一个匹配成功的字符串 $[x, y]$，如果 $1 \leq x &lt; l \leq y \leq r $ 那么 $[x, y]$ 显然是被多算的。我们要排除这种影响。</p><p>定义 $sl_i$ 表示在第 $i$ 位结尾的所有匹配中的起始点（这个值可以用 fail 树随便维护一下），如果 $sl_i &lt; l$，那么存在多算的匹配。如果我们找到 $[l, r]$ 中最大的使得 $sl_i &lt; l$ 的 $i$，记作 $m$，那么在第 $[m + 1, r]$ 位之间结尾的匹配<strong>一定不会</strong>多算，所以直接加上 $suc_r - suc_m$。$m$ 我们可以离线二分或者在线的线段树二分维护。</p><p>接下来处理 $[l, m]$ 之间的匹配。根据刚才的条件，我们一定存在一个模式串，使得 $[l, m]$ <strong>一定是这个模式串的后缀</strong>，所以相当于我们要求出来每一个模式串后缀的匹配数。我们把所有模式串的反串扔到一个 AC 自动机上，对于每一个模式串倒着匹配一遍，就可以以 $\sum |s_i|$ 的复杂度求出每一个模式串的后缀匹配数。把这部分的答案加上就好。</p><p>代码如下：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// By 0x0F</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="meta">#<span class="keyword">ifndef</span> ONLINE_JUDGE</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;my_local.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ll long long</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">read</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> x = <span class="number">0</span>, f = <span class="number">1</span>; <span class="type">char</span> ch = <span class="built_in">getchar</span>();</span><br><span class="line">    <span class="keyword">while</span> (ch &lt; <span class="string">&#x27;0&#x27;</span> || ch &gt; <span class="string">&#x27;9&#x27;</span>) &#123;<span class="keyword">if</span> (ch == <span class="string">&#x27;-&#x27;</span>) f = <span class="number">-1</span>; ch = <span class="built_in">getchar</span>();&#125;</span><br><span class="line">    <span class="keyword">while</span> (ch &gt;= <span class="string">&#x27;0&#x27;</span> &amp;&amp; ch &lt;= <span class="string">&#x27;9&#x27;</span>) &#123;x = x * <span class="number">10</span> + ch - <span class="string">&#x27;0&#x27;</span>; ch = <span class="built_in">getchar</span>();&#125;</span><br><span class="line">    <span class="keyword">return</span> x * f;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// #define FIO</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Trie</span> &#123;</span><br><span class="line">    <span class="type">int</span> son[<span class="number">26</span>];</span><br><span class="line">    <span class="type">int</span> cnt, fail, idx;</span><br><span class="line">&#125; tp[<span class="number">1000010</span>], ts[<span class="number">1000010</span>];</span><br><span class="line"><span class="type">int</span> idxp[<span class="number">500010</span>], idxs[<span class="number">500010</span>]; </span><br><span class="line"><span class="type">int</span> cntp, cnts;</span><br><span class="line">vector&lt;<span class="type">int</span>&gt; Gp[<span class="number">1000010</span>], Gs[<span class="number">1000010</span>];</span><br><span class="line">ll sump[<span class="number">1000010</span>], sums[<span class="number">1000010</span>], suc[<span class="number">5000010</span>];</span><br><span class="line"><span class="type">int</span> dep[<span class="number">1000010</span>], lst[<span class="number">1000010</span>];</span><br><span class="line"><span class="type">int</span> lgt[<span class="number">5000010</span>], pos[<span class="number">5000010</span>];</span><br><span class="line"><span class="type">int</span> ci;</span><br><span class="line">string pp[<span class="number">500010</span>];</span><br><span class="line">vector&lt;ll&gt; g[<span class="number">500010</span>];</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">insertp</span><span class="params">(<span class="type">char</span> s[], <span class="type">int</span> &amp;idx)</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> len = <span class="built_in">strlen</span>(s + <span class="number">1</span>), u = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= len; i++) &#123;</span><br><span class="line">        <span class="type">int</span> &amp;son = tp[u].son[s[i] - <span class="string">&#x27;a&#x27;</span>];</span><br><span class="line">        <span class="keyword">if</span> (!son) son = ++cntp;</span><br><span class="line">        u = son;</span><br><span class="line">    &#125;</span><br><span class="line">    tp[u].cnt++; tp[u].idx = ci;</span><br><span class="line">    idx = u;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">inserts</span><span class="params">(<span class="type">char</span> s[], <span class="type">int</span> &amp;idx)</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> len = <span class="built_in">strlen</span>(s + <span class="number">1</span>), u = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = len; i; i--) &#123;</span><br><span class="line">        <span class="type">int</span> &amp;son = ts[u].son[s[i] - <span class="string">&#x27;a&#x27;</span>];</span><br><span class="line">        <span class="keyword">if</span> (!son) son = ++cnts;</span><br><span class="line">        u = son;</span><br><span class="line">    &#125;</span><br><span class="line">    ts[u].cnt++; ts[u].idx = ci;</span><br><span class="line">    idx = u;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">buildp</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    queue&lt;<span class="type">int</span>&gt; q;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">26</span>; i++) </span><br><span class="line">        <span class="keyword">if</span> (tp[<span class="number">0</span>].son[i]) q.<span class="built_in">push</span>(tp[<span class="number">0</span>].son[i]), Gp[<span class="number">0</span>].<span class="built_in">push_back</span>(tp[<span class="number">0</span>].son[i]);</span><br><span class="line">    <span class="keyword">while</span> (!q.<span class="built_in">empty</span>()) &#123;</span><br><span class="line">        <span class="type">int</span> u = q.<span class="built_in">front</span>(); q.<span class="built_in">pop</span>();</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">26</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (tp[u].son[i]) &#123;</span><br><span class="line">                tp[tp[u].son[i]].fail = tp[tp[u].fail].son[i];</span><br><span class="line">                Gp[tp[tp[u].fail].son[i]].<span class="built_in">push_back</span>(tp[u].son[i]);</span><br><span class="line">                q.<span class="built_in">push</span>(tp[u].son[i]);</span><br><span class="line">            &#125; <span class="keyword">else</span> tp[u].son[i] = tp[tp[u].fail].son[i];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">builds</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    queue&lt;<span class="type">int</span>&gt; q;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">26</span>; i++) </span><br><span class="line">        <span class="keyword">if</span> (ts[<span class="number">0</span>].son[i]) q.<span class="built_in">push</span>(ts[<span class="number">0</span>].son[i]), Gs[<span class="number">0</span>].<span class="built_in">push_back</span>(ts[<span class="number">0</span>].son[i]);</span><br><span class="line">    <span class="keyword">while</span> (!q.<span class="built_in">empty</span>()) &#123;</span><br><span class="line">        <span class="type">int</span> u = q.<span class="built_in">front</span>(); q.<span class="built_in">pop</span>();</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">26</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (ts[u].son[i]) &#123;</span><br><span class="line">                ts[ts[u].son[i]].fail = ts[ts[u].fail].son[i];</span><br><span class="line">                Gs[ts[ts[u].fail].son[i]].<span class="built_in">push_back</span>(ts[u].son[i]);</span><br><span class="line">                q.<span class="built_in">push</span>(ts[u].son[i]);</span><br><span class="line">            &#125; <span class="keyword">else</span> ts[u].son[i] = ts[ts[u].fail].son[i];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">26</span>; i++) &#123;</span><br><span class="line">        <span class="type">int</span> v = tp[u].son[i];</span><br><span class="line">        <span class="keyword">if</span> (v) &#123;</span><br><span class="line">            dep[v] = dep[u] + <span class="number">1</span>;</span><br><span class="line">            <span class="built_in">dfs</span>(v);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfsp</span><span class="params">(<span class="type">int</span> u)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> v : Gp[u]) &#123;</span><br><span class="line">        sump[v] = sump[u] + tp[v].cnt;</span><br><span class="line">        lst[v] = lst[u];</span><br><span class="line">        <span class="keyword">if</span> (tp[v].cnt) lst[v] = v;</span><br><span class="line">        <span class="built_in">dfsp</span>(v);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfss</span><span class="params">(<span class="type">int</span> u)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> v : Gs[u]) &#123;</span><br><span class="line">        sums[v] = sums[u] + ts[v].cnt;</span><br><span class="line">        <span class="built_in">dfss</span>(v);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">match</span><span class="params">(<span class="type">char</span> s[])</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> len = <span class="built_in">strlen</span>(s + <span class="number">1</span>), u = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= len; i++) &#123;</span><br><span class="line">        suc[i] = suc[i - <span class="number">1</span>];</span><br><span class="line">        u = tp[u].son[s[i] - <span class="string">&#x27;a&#x27;</span>];</span><br><span class="line">        pos[i] = u;</span><br><span class="line">        suc[i] += sump[u];</span><br><span class="line">        lgt[i] = dep[lst[u]];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Query</span> &#123;<span class="type">int</span> l, r;&#125; qu[<span class="number">500010</span>];</span><br><span class="line"><span class="type">char</span> t[<span class="number">5000010</span>], pt[<span class="number">1000010</span>];</span><br><span class="line">vector&lt;<span class="type">int</span>&gt; seg[<span class="number">5000010</span>];</span><br><span class="line">vector&lt;pair&lt;<span class="type">int</span>, <span class="type">int</span>&gt;&gt; qv[<span class="number">5000010</span>]; </span><br><span class="line"><span class="type">int</span> mxr[<span class="number">5000010</span>];</span><br><span class="line">set&lt;<span class="type">int</span>&gt; st;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> n = <span class="built_in">read</span>(), q = <span class="built_in">read</span>();</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">&quot;%s&quot;</span>, t + <span class="number">1</span>);</span><br><span class="line">    <span class="type">int</span> nt = <span class="built_in">strlen</span>(t + <span class="number">1</span>);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        <span class="built_in">scanf</span>(<span class="string">&quot;%s&quot;</span>, pt + <span class="number">1</span>); ci++;</span><br><span class="line">        <span class="type">int</span> len = <span class="built_in">strlen</span>(pt + <span class="number">1</span>);</span><br><span class="line">        pp[i] = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> x = len; x &gt;= <span class="number">1</span>; x--) pp[i] += pt[x];</span><br><span class="line">        <span class="built_in">insertp</span>(pt, idxp[i]);</span><br><span class="line">        <span class="built_in">inserts</span>(pt, idxs[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">dfs</span>(<span class="number">0</span>);</span><br><span class="line">    <span class="built_in">buildp</span>(); <span class="built_in">builds</span>();</span><br><span class="line">    <span class="built_in">dfsp</span>(<span class="number">0</span>); <span class="built_in">dfss</span>(<span class="number">0</span>);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> x = <span class="number">1</span>; x &lt;= n; x++) &#123;</span><br><span class="line">        <span class="type">int</span> len = pp[x].<span class="built_in">size</span>();</span><br><span class="line">        g[x].<span class="built_in">resize</span>(len + <span class="number">2</span>, <span class="number">0</span>);</span><br><span class="line">        <span class="type">int</span> u = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= len; i++) &#123;</span><br><span class="line">            u = ts[u].son[pp[x][i - <span class="number">1</span>] - <span class="string">&#x27;a&#x27;</span>];</span><br><span class="line">            g[x][i] = sums[u] + g[x][i - <span class="number">1</span>];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">match</span>(t);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= nt; i++) &#123;</span><br><span class="line">        <span class="keyword">if</span> (lgt[i] == <span class="number">0</span>) <span class="keyword">continue</span>;</span><br><span class="line">        <span class="type">int</span> start = i - lgt[i] + <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">if</span> (start &gt;= <span class="number">1</span>) seg[start].<span class="built_in">push_back</span>(i);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= q; i++) &#123;</span><br><span class="line">        qu[i].l = <span class="built_in">read</span>();</span><br><span class="line">        qu[i].r = <span class="built_in">read</span>();</span><br><span class="line">        qv[qu[i].l].<span class="built_in">push_back</span>(&#123;qu[i].r, i&#125;);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> l = <span class="number">1</span>; l &lt;= nt; l++) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">auto</span> tq : qv[l]) &#123;</span><br><span class="line">            <span class="type">int</span> r = tq.first, id = tq.second;</span><br><span class="line">            <span class="keyword">if</span> (st.<span class="built_in">empty</span>()) &#123;mxr[id] = <span class="number">-1</span>; <span class="keyword">continue</span>;&#125;</span><br><span class="line">            <span class="keyword">auto</span> p = st.<span class="built_in">upper_bound</span>(r);</span><br><span class="line">            <span class="keyword">if</span> (p == st.<span class="built_in">begin</span>()) &#123;mxr[id] = <span class="number">-1</span>; <span class="keyword">continue</span>;&#125;</span><br><span class="line">            p--;</span><br><span class="line">            <span class="keyword">if</span> (*p &lt; l) &#123;mxr[id] = <span class="number">-1</span>; <span class="keyword">continue</span>;&#125;</span><br><span class="line">            mxr[id] = *p;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> r : seg[l]) st.<span class="built_in">insert</span>(r);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= q; i++) &#123;</span><br><span class="line">        ll ans = <span class="number">0</span>; </span><br><span class="line">        <span class="type">int</span> l = qu[i].l, r = qu[i].r;</span><br><span class="line">        <span class="type">int</span> kr = mxr[i];</span><br><span class="line">        <span class="keyword">if</span> (kr == <span class="number">-1</span>) &#123;</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">&quot;%lld &quot;</span>, suc[r] - suc[l - <span class="number">1</span>]); </span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        ans += suc[r] - suc[kr];</span><br><span class="line">        <span class="type">int</span> num = tp[lst[pos[kr]]].idx;</span><br><span class="line">        ans += g[num][kr - l + <span class="number">1</span>];</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;%lld &quot;</span>, ans);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">signed</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="meta">#<span class="keyword">ifdef</span> FIO</span></span><br><span class="line">string f_name = <span class="string">&quot;xxx&quot;</span>;</span><br><span class="line"><span class="built_in">freopen</span>((f_name + <span class="string">&quot;.in&quot;</span>).<span class="built_in">c_str</span>(), <span class="string">&quot;r&quot;</span>, stdin);</span><br><span class="line"><span class="built_in">freopen</span>((f_name + <span class="string">&quot;.out&quot;</span>).<span class="built_in">c_str</span>(), <span class="string">&quot;w&quot;</span>, stdout);</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">    <span class="type">int</span> REP = <span class="number">1</span>;</span><br><span class="line">    <span class="comment">// REP = read();</span></span><br><span class="line">    <span class="keyword">while</span> (REP--) <span class="built_in">solve</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>ps：写得有点烂，请多多包涵。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;看到字符串匹配，我们就要往 AC 自动机上去想。我们根据 AC 自动机的性质，我们很容易得知在第 $i$ 位结尾的匹配有多少个，所以我们可以很轻松地得到一个文本串的&lt;strong&gt;前缀&lt;/strong&gt;的匹配数。&lt;/p&gt;
&lt;p&gt;因此，我们考虑：假设第 $i$ 个位置的匹配数</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="字符串" scheme="https://akioi.dev/tags/%E5%AD%97%E7%AC%A6%E4%B8%B2/"/>
    
    <category term="线段树" scheme="https://akioi.dev/tags/%E7%BA%BF%E6%AE%B5%E6%A0%91/"/>
    
    <category term="AC 自动机" scheme="https://akioi.dev/tags/AC-%E8%87%AA%E5%8A%A8%E6%9C%BA/"/>
    
  </entry>
  
  <entry>
    <title>题解：P8569 [JRKSJ R6] 第七学区</title>
    <link href="https://akioi.dev/2025/11/05/p8569-jrksj-r6/"/>
    <id>https://akioi.dev/2025/11/05/p8569-jrksj-r6/</id>
    <published>2025-11-05T10:13:02.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>这绝对是一个非常好的题，中午去吃一顿饭的功夫就想出来这个小巧思。</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>首先我们考虑按位或的性质。</p><p>假设有一个 0&#x2F;1 数组。由性质得，如果一个区间只要存在 1，那么这个区间的贡献就是 1。定义 $f_i$ 表示以 $i$ 结尾的所有区间的贡献和，所以 $f_i$ 显然就是间 $[1,i]$ 中最后一个 1 出现的位置，答案就是 $\sum f_i$。回到原题，我们会很容易想到把每一个数拆位来计算贡献，对于每一位，从头到尾跑一遍。注意其实 $a_i$ 和 $f_i$ 其实没必要存下来，就可以省下来空间。时间复杂度 $O(n \log V)$，会拿到 30pts 的好成绩。</p><p>代码如下：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> READ;</span><br><span class="line"><span class="type">int</span> lst[<span class="number">70</span>];</span><br><span class="line">ull ans;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> n;</span><br><span class="line">    <span class="built_in">init</span>(n);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        ull x = <span class="built_in">read</span>();</span><br><span class="line">        <span class="comment">// Brute Force</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> b = <span class="number">0</span>; b &lt; <span class="number">64</span>; b++) &#123;</span><br><span class="line">            <span class="keyword">if</span> ((x &gt;&gt; b) &amp; <span class="number">1</span>) lst[b] = i;</span><br><span class="line">            ans += (<span class="number">1ll</span> &lt;&lt; b) * lst[b];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    cout &lt;&lt; ans &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们考虑优化。首先定义 $l_i$ 表示当前位置第 $i$ 个数位最后一个 1 出现的位置，那么对于当前这个位置的答案就是 $\sum 2^i \times lst_i$。我们发现拆数位比拆位置的位数多很多，那我们为什么不拆位置呢？所以我们定义 $c_i$ 表示位置<strong>二进制拆分</strong>后第 $i$ 位为 1 的每一个数位<strong>是否存在</strong>最后一个 1 的情况。我们发现按照状压的方法存，$c_i$ 天然地帮我们乘好了每一个数位的系数。最终这个位置的答案就是 $\sum 2^i \times c_i$（注意这里的 $i$ 表示拆分的位置，而不是数位）。</p><p>我们考虑怎么维护 $c_i$？过程可以分成两步，一步是删去新加数的数位上原来的贡献，一步是加上现在的贡献。假设当前位置上的值是 $x$，第一步给每一个 $c_i$ 执行 $c_i \leftarrow  c_i \land \overline{x}$，第二步对于拆分位置后是 1 的 $c_i$ 执行 $c_i \leftarrow  c_i \lor x$，最后把答案合并算一下就行了。满分代码如下：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> READ;</span><br><span class="line">ull cnt[<span class="number">30</span>], ans;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> n, l = <span class="number">0</span>;</span><br><span class="line">    <span class="built_in">init</span>(n);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">        ull x = <span class="built_in">read</span>();</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> b = <span class="number">0</span>; b &lt;= l; b++) cnt[b] &amp;= (~x);</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> b = <span class="number">0</span>; b &lt;= l; b++) cnt[b] += x * ((i + <span class="number">1</span> &gt;&gt; b) &amp; <span class="number">1</span>);</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> b = <span class="number">0</span>; b &lt;= l; b++) ans += cnt[b] * (<span class="number">1</span> &lt;&lt; b);</span><br><span class="line">        l += ((i &amp; -i) == i); </span><br><span class="line">    &#125;</span><br><span class="line">    cout &lt;&lt; ans &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>时间复杂度 $O(n \log n)$，这个数据范围虽然看着十分恐怖，但是实际上只需要 1s 左右，跑得飞快。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;这绝对是一个非常好的题，中午去吃一顿饭的功夫就想出来这个小巧思。&lt;/p&gt;
&lt;h2 id=&quot;思路&quot;&gt;&lt;a href=&quot;#思路&quot; class=&quot;headerlink&quot; title=&quot;思路&quot;&gt;&lt;/a&gt;思路&lt;/h2&gt;&lt;p&gt;首先我们考虑按位或的性质。&lt;/p&gt;
&lt;p&gt;假设有一个 0&amp;#</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="位运算" scheme="https://akioi.dev/tags/%E4%BD%8D%E8%BF%90%E7%AE%97/"/>
    
  </entry>
  
  <entry>
    <title>题解 P3059 [USACO12NOV] Concurrently Balanced Strings G</title>
    <link href="https://akioi.dev/2024/08/13/p3059-usaco12nov-concurrently-balanced-strings/"/>
    <id>https://akioi.dev/2024/08/13/p3059-usaco12nov-concurrently-balanced-strings/</id>
    <published>2024-08-13T08:02:33.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>一种 <code>vector&lt;int&gt;, vector&lt;int&gt;</code> 的 map 做法，代码稍长一些但是特别好想。</p><p>先考虑 $k &#x3D; 1$ 时的做法，后面 $k$ 增大时在原基础上改动一点就可以了。</p><p>看到左右括号，我们容易想到遇到左括号加 $1$，右括号减 $1$，记第到 $i$ 个位置的前缀和为 $sum_i$。显然，区间 $[l,r]$ 若是合法的，必须满足以下条件：</p><ul><li>左括号和右括号的数量相等。</li><li>在任何位置，前面的右括号个数不能超过左括号。</li></ul><p>用数学的形式表达，就是：</p><ul><li>$sum_r - sum_{l-1} &#x3D; 0$。</li><li>对于 $[l, r]$ 之间的任意一点 $i$，满足 $sum_i - sum_{l - 1} \geq 0$。</li></ul><p>移项，得：</p><ul><li>$sum_r &#x3D; sum_{l-1}$。</li><li>对于 $[l, r]$ 之间的任意一点 $i$，满足 $sum_i \geq sum_{l - 1}$。</li></ul><p>我们分开考虑每个条件。</p><p>若假设 $l$ 为当前计算区间的左端点，那么若存在一点 $i$ 满足 $sum_i &lt; sum_{l - 1}$ 且 $i \geq l$，那么 $i$ 以及后面的所有点和 $l$ 所构成的区间都是不合法的。那么我们找到 $l$ 右边第一个比 $sum_{l - 1}$ 小的位置 $R$（可以用单调栈预处理），那么 $R$ 以前的位置都可能合法。条件二的限制就解决了。结合条件一，我们预处理每个 $sum$ 值都出现过的坐标，用 vector 存起来排序，在 $sum_{l - 1}$ 查找 $[i, R - 1]$ 之间有几个坐标，加到答案即可。</p><p>对于增加的 $k$，$R$ 取 $k$ 个数里的最小值，由于 $k \leq 10$，我们直接把 $k$ 个 $sum$ 放到一个 vector 里并做成 map，每次用 vector 查就好了，自己想想就清楚了。</p><p>时间复杂度 $O(nk \log n)$。</p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// By 0x0F</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="comment">// #define AT_contest</span></span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> AT_contest</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;atcoder/all&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> atcoder;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">// #define int long long</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> fi first</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> se second</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> pb push_back</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> sz(x) (x).size()</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> all(x) (x).begin(), (x).end()</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> pii pair&lt;int, int&gt;</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> mpii map&lt;int, int&gt;</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> vi vector&lt;int&gt;</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> fr front</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> bk back</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> ls(x) (x &lt;&lt; 1)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> rs(x) (x &lt;&lt; 1 | 1)</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">read</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> x = <span class="number">0</span>, f = <span class="number">1</span>; <span class="type">char</span> ch = <span class="built_in">getchar</span>();</span><br><span class="line">    <span class="keyword">while</span> (ch &lt; <span class="string">&#x27;0&#x27;</span> || ch &gt; <span class="string">&#x27;9&#x27;</span>) &#123;<span class="keyword">if</span> (ch == <span class="string">&#x27;-&#x27;</span>) f = <span class="number">-1</span>; ch = <span class="built_in">getchar</span>();&#125;</span><br><span class="line">    <span class="keyword">while</span> (ch &gt;= <span class="string">&#x27;0&#x27;</span> &amp;&amp; ch &lt;= <span class="string">&#x27;9&#x27;</span>) &#123;x = x * <span class="number">10</span> + ch - <span class="number">48</span>; ch = <span class="built_in">getchar</span>();&#125;</span><br><span class="line">    <span class="keyword">return</span> x * f;</span><br><span class="line">&#125;</span><br><span class="line"><span class="meta">#<span class="keyword">define</span> inf 0x7fffffff</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> INF 0x3f3f3f3f3f3f3f3fll</span></span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(int)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> RETURN_MAIN signed</span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">if</span> !defined(int)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> RETURN_MAIN int</span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">char</span> s[<span class="number">12</span>][<span class="number">50010</span>];</span><br><span class="line"><span class="type">int</span> sum[<span class="number">12</span>][<span class="number">50010</span>], rmax[<span class="number">12</span>][<span class="number">50010</span>];</span><br><span class="line">map&lt;vi, vi&gt; mp;</span><br><span class="line"><span class="function">RETURN_MAIN <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> k = <span class="built_in">read</span>(), n = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++) <span class="built_in">scanf</span>(<span class="string">&quot;%s&quot;</span>, s[i] + <span class="number">1</span>);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++)</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= n; j++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (s[i][j] == <span class="string">&#x27;(&#x27;</span>) sum[i][j] = sum[i][j - <span class="number">1</span>] + <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">else</span> sum[i][j] = sum[i][j - <span class="number">1</span>] - <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++) sum[i][n + <span class="number">1</span>] = -inf;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++) &#123;</span><br><span class="line">        stack&lt;<span class="type">int</span>&gt; st; st.<span class="built_in">push</span>(n + <span class="number">1</span>);</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = n; j &gt;= <span class="number">0</span>; j--) &#123;</span><br><span class="line">            <span class="keyword">while</span> (!st.<span class="built_in">empty</span>() &amp;&amp; sum[i][st.<span class="built_in">top</span>()] &gt;= sum[i][j]) st.<span class="built_in">pop</span>();</span><br><span class="line">            rmax[i][j] = st.<span class="built_in">top</span>();</span><br><span class="line">            st.<span class="built_in">push</span>(j);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j &lt;= n; j++) &#123;</span><br><span class="line">        vi tmp;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++) tmp.<span class="built_in">pb</span>(sum[i][j]);</span><br><span class="line">        mp[tmp].<span class="built_in">pb</span>(j);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= n; j++) &#123;</span><br><span class="line">        <span class="type">int</span> R = inf;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++) R = <span class="built_in">min</span>(R, rmax[i][j - <span class="number">1</span>] - <span class="number">1</span>);</span><br><span class="line">        <span class="comment">// R 为能达到的最远点</span></span><br><span class="line">        vi tmp;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= k; i++) tmp.<span class="built_in">pb</span>(sum[i][j - <span class="number">1</span>]);</span><br><span class="line">        <span class="keyword">if</span> (R &lt;= j) <span class="keyword">continue</span>;</span><br><span class="line">        vi pos = mp[tmp];</span><br><span class="line">        <span class="type">int</span> vl = <span class="built_in">lower_bound</span>(<span class="built_in">all</span>(pos), j) - pos.<span class="built_in">begin</span>(), </span><br><span class="line">            vr = <span class="built_in">upper_bound</span>(<span class="built_in">all</span>(pos), R) - pos.<span class="built_in">begin</span>();</span><br><span class="line">        ans += vr - vl;</span><br><span class="line">    &#125;</span><br><span class="line">    cout &lt;&lt; ans;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;思路&quot;&gt;&lt;a href=&quot;#思路&quot; class=&quot;headerlink&quot; title=&quot;思路&quot;&gt;&lt;/a&gt;思路&lt;/h2&gt;&lt;p&gt;一种 &lt;code&gt;vector&amp;lt;int&amp;gt;, vector&amp;lt;int&amp;gt;&lt;/code&gt; 的 map 做法，代码稍长一些但是</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="哈希" scheme="https://akioi.dev/tags/%E5%93%88%E5%B8%8C/"/>
    
    <category term="动态规划" scheme="https://akioi.dev/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
    
    <category term="平衡树" scheme="https://akioi.dev/tags/%E5%B9%B3%E8%A1%A1%E6%A0%91/"/>
    
  </entry>
  
  <entry>
    <title>题解 [KUPC2020F] GRIDMST</title>
    <link href="https://akioi.dev/2024/08/08/kupc2020f-gridmst/"/>
    <id>https://akioi.dev/2024/08/08/kupc2020f-gridmst/</id>
    <published>2024-08-08T08:09:11.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>首先我们根据贪心的策略，很容易想出来一定要把最上边的那一行和最左边的那一列全部连起来，剩下的点连向左边或者上边就可以了。$O(n ^ 2)$ 的暴力做法就是枚举每个点是连向左边还是上边，直接加上每个点的贡献就可以了。</p><p>对于 $O(n \log n)$ 的做法，我们就不能挨个考虑每个点连接的方向了。我们进而分析每个点连接的方向和数组 $a, b, c, d$ 的关系。显然，我们选择连上面而不是左边时，满足：</p><p>$$a_{i - 1} + b_j &lt; c_i + d_{j - 1}$$</p><p>移项，得</p><p>$$a_{i - 1} - c_i &lt; d_{j - 1} - b_j$$</p><p>即</p><p>$$d_{j - 1} - b_j &gt; a_{i - 1} - c_i$$</p><p>而对于每一行来说，$a_{i - 1} - c_i$ 是固定不变的。所以我们可以预处理好 $d_{j - 1} - b_j$ 的值，记作 $diff$，每次在 $diff$ 上二分 $a_{i - 1} - c_i$ 的值，这个值右边的所有数就是连向上面的，左边的所有数就是连向左边的，进而我们可以求出连向上面和左边的点的个数，分别记作 $n_U$ 和 $n_L$。</p><p>对于计算贡献，我们可以把 $a, c$ 和 $b, d$ 分开考虑。$a, c$ 的计算比较简单，我们只需要加上 $n_U$ 个 $a_{i - 1}$ 和 $n_L$ 个 $c_i$。$b, d$ 的处理比较麻烦一些，我们可以把 $b_j, d_{j - 1}, d_{j - 1} - b_j$，放在一个结构体里，按照 $diff$ 值排序之后，对 $b$ 和 $d$ 做前缀和，二分位置前的加上 $d$，位置后的加上 $b$ 就可以了，当然也有其他的方法，这里就不多说了。</p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><p>代码实现时需要注意一点小细节，自己想想就明白了。</p><p><a href="https://atcoder.jp/contests/kupc2020/submissions/56457018">AC Record</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;思路&quot;&gt;&lt;a href=&quot;#思路&quot; class=&quot;headerlink&quot; title=&quot;思路&quot;&gt;&lt;/a&gt;思路&lt;/h2&gt;&lt;p&gt;首先我们根据贪心的策略，很容易想出来一定要把最上边的那一行和最左边的那一列全部连起来，剩下的点连向左边或者上边就可以了。$O(n ^ 2)$</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="二分" scheme="https://akioi.dev/tags/%E4%BA%8C%E5%88%86/"/>
    
    <category term="贪心" scheme="https://akioi.dev/tags/%E8%B4%AA%E5%BF%83/"/>
    
    <category term="前缀和" scheme="https://akioi.dev/tags/%E5%89%8D%E7%BC%80%E5%92%8C/"/>
    
  </entry>
  
  <entry>
    <title>题解 [ABC344E] Insert or Erase</title>
    <link href="https://akioi.dev/2024/03/10/abc344e-insert-or-erase/"/>
    <id>https://akioi.dev/2024/03/10/abc344e-insert-or-erase/</id>
    <published>2024-03-10T00:57:30.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution:"></a>Solution:</h2><p>本题需要模拟一个链表，考虑需要加入时需要知道一个点的后继，删除时需要知道一个点的前驱和后继，所以我们采用双向链表维护。用数组维护每个点的前驱和后继。由于值域是 $10^9$ 的，所以我们采用<code>map</code>维护。</p><p>首先考虑构建链表。我们把序列中的点顺次放入链表中，具体地说，对于每个点 $a_i$，它的前驱是 $a_{i-1}$，后继是 $a_{i+1}$。特别地，我们建立两个虚拟节点，分别作为 $a_1$ 的前驱和 $a_n$ 的后继。</p><p>考虑添加点。我们很容易得知要添加点的左右两个点 $L$ 和 $R$，设添加的点为 $X$，对于后继，把 $L$ 的后继连向 $X$，$X$ 的后继连向 $R$，前驱同理，如图所示：</p><p><img src="https://s21.ax1x.com/2024/03/10/pFy8CH1.png"></p><p><img src="https://s21.ax1x.com/2024/03/10/pFy89BR.png"></p><p>考虑删除。我们很容易得知要删除点的左右两个点 $L$ 和 $R$，把 $L$ 的后继连向 $R$，$R$ 的前驱连向 $L$ 如图所示：</p><p><img src="https://s21.ax1x.com/2024/03/10/pFy8iAx.png"></p><p>最后从最左边的虚拟点开始，向右寻找后继输出，直至寻找到最右边的点，输出结束。</p><p>时间复杂度 $O(n \log n)$。</p><h2 id="Code"><a href="#Code" class="headerlink" title="Code:"></a>Code:</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// By 0x0F</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="meta">#<span class="keyword">define</span> int long long</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">read</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> x = <span class="number">0</span>, f = <span class="number">1</span>; <span class="type">char</span> ch = <span class="built_in">getchar</span>();</span><br><span class="line">    <span class="keyword">while</span> (ch &lt; <span class="string">&#x27;0&#x27;</span> || ch &gt; <span class="string">&#x27;9&#x27;</span>) &#123;<span class="keyword">if</span> (ch == <span class="string">&#x27;-&#x27;</span>) f = <span class="number">-1</span>; ch = <span class="built_in">getchar</span>();&#125;</span><br><span class="line">    <span class="keyword">while</span> (ch &gt;= <span class="string">&#x27;0&#x27;</span> &amp;&amp; ch &lt;= <span class="string">&#x27;9&#x27;</span>) &#123;x = x * <span class="number">10</span> + ch - <span class="number">48</span>; ch = <span class="built_in">getchar</span>();&#125;</span><br><span class="line">    <span class="keyword">return</span> x * f;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> pL = <span class="number">-1</span>, pR = <span class="number">1145141919810LL</span>;</span><br><span class="line">unordered_map&lt;<span class="type">int</span> ,<span class="type">int</span>&gt; nxt, frm;</span><br><span class="line"><span class="type">int</span> a[<span class="number">200010</span>];</span><br><span class="line"><span class="function"><span class="type">signed</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> n = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) a[i] = <span class="built_in">read</span>();</span><br><span class="line">    a[<span class="number">0</span>] = pL, a[n + <span class="number">1</span>] = pR;</span><br><span class="line">    nxt[pL] = a[<span class="number">1</span>], nxt[a[n]] = pR, frm[pR] = a[n], frm[a[<span class="number">1</span>]] = pL;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt; n; i++) nxt[a[i]] = a[i + <span class="number">1</span>];</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">2</span>; i &lt;= n; i++) frm[a[i]] = a[i - <span class="number">1</span>];</span><br><span class="line">    <span class="type">int</span> q = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">while</span> (q--) &#123;</span><br><span class="line">        <span class="type">int</span> op = <span class="built_in">read</span>();</span><br><span class="line">        <span class="keyword">if</span> (op == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="type">int</span> x = <span class="built_in">read</span>(), y = <span class="built_in">read</span>();</span><br><span class="line">            <span class="type">int</span> xl = x, xr = nxt[x];</span><br><span class="line">            nxt[xl] = y, nxt[y] = xr;</span><br><span class="line">            frm[xr] = y, frm[y] = xl;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="type">int</span> x = <span class="built_in">read</span>();</span><br><span class="line">            <span class="type">int</span> xl = frm[x], xr = nxt[x];</span><br><span class="line">            nxt[xl] = xr, frm[xr] = xl;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="type">int</span> st = nxt[pL];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> st = nxt[pL];</span><br><span class="line">    <span class="keyword">while</span> (st != pR) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;%lld &quot;</span>, st);</span><br><span class="line">        st = nxt[st];</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Solution&quot;&gt;&lt;a href=&quot;#Solution&quot; class=&quot;headerlink&quot; title=&quot;Solution:&quot;&gt;&lt;/a&gt;Solution:&lt;/h2&gt;&lt;p&gt;本题需要模拟一个链表，考虑需要加入时需要知道一个点的后继，删除时需要知道一个点的前驱和后</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="链表" scheme="https://akioi.dev/tags/%E9%93%BE%E8%A1%A8/"/>
    
    <category term="模拟" scheme="https://akioi.dev/tags/%E6%A8%A1%E6%8B%9F/"/>
    
  </entry>
  
  <entry>
    <title>题解 Divisible Pairs</title>
    <link href="https://akioi.dev/2024/02/21/cf1931d-divisible-pairs/"/>
    <id>https://akioi.dev/2024/02/21/cf1931d-divisible-pairs/</id>
    <published>2024-02-21T09:52:24.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution:"></a>Solution:</h2><p>首先转换一下题意。</p><p>对于 $a_i$ 和 $a_j$，满足 $a_i + a_j$ 可被 $x$ 整除，也就是满足 $a_i + a_j \equiv 0 \pmod{x}$，两边同时减 $a_j$，得 $a_i \equiv -a_j \pmod{x}$，即 $a_j \equiv -a_i \pmod{x}$；满足 $a_i - a_j$ 可被 $y$ 整除，也就是满足 $a_i - a_j \equiv 0 \pmod{y}$，两边同时加 $a_j$，得 $a_i \equiv a_j \pmod{y}$。</p><p>有一个问题，就是处理 $-a_i \mod x$ 的方法。显然 $a_i \equiv x-a_i \mod x \pmod{x}$，所以使用 $(x-a_i \mod x) \mod x$ 来处理。</p><p>开个<code>map</code>数组，以每个数模 $x$ 和模 $i$ 的值作为下标，对于每个数 $a_i$，其对应的答案就是 $mp_{-a_i \mod x,a_i \mod y}$。</p><h2 id="Code"><a href="#Code" class="headerlink" title="Code:"></a>Code:</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// By 0x0F</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="meta">#<span class="keyword">define</span> int long long</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">read</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> x = <span class="number">0</span>, f = <span class="number">1</span>; <span class="type">char</span> ch = <span class="built_in">getchar</span>();</span><br><span class="line">    <span class="keyword">while</span> (ch &lt; <span class="string">&#x27;0&#x27;</span> || ch &gt; <span class="string">&#x27;9&#x27;</span>) &#123;<span class="keyword">if</span> (ch == <span class="string">&#x27;-&#x27;</span>) f = <span class="number">-1</span>; ch = <span class="built_in">getchar</span>();&#125;</span><br><span class="line">    <span class="keyword">while</span> (ch &gt;= <span class="string">&#x27;0&#x27;</span> &amp;&amp; ch &lt;= <span class="string">&#x27;9&#x27;</span>) &#123;x = x * <span class="number">10</span> + ch - <span class="number">48</span>; ch = <span class="built_in">getchar</span>();&#125;</span><br><span class="line">    <span class="keyword">return</span> x * f;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">int</span> a[<span class="number">200010</span>];</span><br><span class="line">map&lt;pair&lt;<span class="type">int</span>, <span class="type">int</span>&gt;, <span class="type">int</span>&gt; mp;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> n = <span class="built_in">read</span>(), x = <span class="built_in">read</span>(), y = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) a[i] = <span class="built_in">read</span>();</span><br><span class="line">    mp.<span class="built_in">clear</span>();</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) mp[&#123;a[i] % x,a[i] % y&#125;]++;</span><br><span class="line">    <span class="type">int</span> ans=<span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        ans += mp[&#123;(x - a[i] % x) % x, a[i] % y&#125;]; <span class="comment">//累加答案</span></span><br><span class="line">        <span class="keyword">if</span> (a[i] % x == <span class="number">0</span>) ans--; <span class="comment">//当 a_i 为 0 时，自己加自己，自己减自己都可以构成整除，所以减去一个答案</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;%lld\n&quot;</span>, ans / <span class="number">2</span>); <span class="comment">//每个答案被重复算了一次</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">signed</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> t = <span class="built_in">read</span>();</span><br><span class="line">    <span class="keyword">while</span> (t--) <span class="built_in">solve</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Solution&quot;&gt;&lt;a href=&quot;#Solution&quot; class=&quot;headerlink&quot; title=&quot;Solution:&quot;&gt;&lt;/a&gt;Solution:&lt;/h2&gt;&lt;p&gt;首先转换一下题意。&lt;/p&gt;
&lt;p&gt;对于 $a_i$ 和 $a_j$，满足 $a_i + </summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="数学" scheme="https://akioi.dev/tags/%E6%95%B0%E5%AD%A6/"/>
    
    <category term="哈希" scheme="https://akioi.dev/tags/%E5%93%88%E5%B8%8C/"/>
    
  </entry>
  
  <entry>
    <title>题解 [ABC341E] Alternating String</title>
    <link href="https://akioi.dev/2024/02/18/abc341e-alternating-string/"/>
    <id>https://akioi.dev/2024/02/18/abc341e-alternating-string/</id>
    <published>2024-02-18T03:42:50.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>想到一种和其他题解不一样的做法，就写一下吧。</p><h2 id="Solution："><a href="#Solution：" class="headerlink" title="Solution："></a>Solution：</h2><p>设设个序列为 $S$，如果有一个位置 $i$ 满足 $S_i&#x3D;S_{i-1}$，那么把 $i$ 的位置记录下来（也就是说记录两个数相同的位置），由于数据范围是 $5 \times 10^5$ 的，所以把位置可以用<code>bool</code>数组存下来，查询时如果 $[l+1,r]$ 内没有被标记的位置，就是合法的，否则是不合法的，我们可以用线段树维护这个数组。</p><p>对于修改，显然修改后区间内数的相对关系是不会改变的，修改区间外数的相对关系当然也不会改变，可能改变的只有 $[l-1,l]$ 和 $[r,r+1]$，所以我们只需要从新判断这两个位置的数的关系是相同的还是不同的，并作出修改就好了。</p><p>如何得知修改后每个数是 $0$ 还是 $1$？我们可以维护一下每个数字被取反了几次，修改时区间加上 $1$，设这个数被取反了 $k$ 次，原始的值是 $0&#x2F;1$，那么查询就是 $(k\mod 2 + 0&#x2F;1) \mod 2$。区间加、单点查询用差分就可以维护。</p><p>时间复杂度 $O(Q \log N)$。</p><h2 id="Code"><a href="#Code" class="headerlink" title="Code:"></a>Code:</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// By 0x0F</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="comment">//#define int long long</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">read</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="type">int</span> x=<span class="number">0</span>,f=<span class="number">1</span>;<span class="type">char</span> ch=<span class="built_in">getchar</span>();</span><br><span class="line"><span class="keyword">while</span>(ch&lt;<span class="string">&#x27;0&#x27;</span>||ch&gt;<span class="string">&#x27;9&#x27;</span>)&#123;<span class="keyword">if</span>(ch==<span class="string">&#x27;-&#x27;</span>)f=<span class="number">-1</span>;ch=<span class="built_in">getchar</span>();&#125;</span><br><span class="line"><span class="keyword">while</span>(ch&gt;=<span class="string">&#x27;0&#x27;</span>&amp;&amp;ch&lt;=<span class="string">&#x27;9&#x27;</span>)&#123;x=x*<span class="number">10</span>+ch<span class="number">-48</span>;ch=<span class="built_in">getchar</span>();&#125;</span><br><span class="line"><span class="keyword">return</span> x*f;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Segtree</span>&#123;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Node</span>&#123;</span><br><span class="line"><span class="type">int</span> l,r,val;</span><br><span class="line">&#125;tree[<span class="number">2000010</span>];</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">pushup</span><span class="params">(<span class="type">int</span> p)</span></span>&#123;</span><br><span class="line">tree[p].val=tree[p&lt;&lt;<span class="number">1</span>].val+tree[p&lt;&lt;<span class="number">1</span>|<span class="number">1</span>].val;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">build</span><span class="params">(<span class="type">int</span> p,<span class="type">int</span> l,<span class="type">int</span> r)</span></span>&#123;</span><br><span class="line">tree[p].l=l,tree[p].r=r;</span><br><span class="line"><span class="keyword">if</span>(l==r)<span class="keyword">return</span>;</span><br><span class="line"><span class="type">int</span> mid=l+r&gt;&gt;<span class="number">1</span>;</span><br><span class="line"><span class="built_in">build</span>(p&lt;&lt;<span class="number">1</span>,l,mid);</span><br><span class="line"><span class="built_in">build</span>(p&lt;&lt;<span class="number">1</span>|<span class="number">1</span>,mid<span class="number">+1</span>,r);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">modify</span><span class="params">(<span class="type">int</span> p,<span class="type">int</span> loc,<span class="type">int</span> val)</span></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(tree[p].l==tree[p].r)&#123;tree[p].val+=val;<span class="keyword">return</span>;&#125;</span><br><span class="line"><span class="type">int</span> mid=tree[p].l+tree[p].r&gt;&gt;<span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span>(loc&lt;=mid)<span class="built_in">modify</span>(p&lt;&lt;<span class="number">1</span>,loc,val);</span><br><span class="line"><span class="keyword">else</span> <span class="built_in">modify</span>(p&lt;&lt;<span class="number">1</span>|<span class="number">1</span>,loc,val);</span><br><span class="line"><span class="built_in">pushup</span>(p);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">equal</span><span class="params">(<span class="type">int</span> p,<span class="type">int</span> loc,<span class="type">int</span> val)</span></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(tree[p].l==tree[p].r)&#123;tree[p].val=val;<span class="keyword">return</span>;&#125;</span><br><span class="line"><span class="type">int</span> mid=tree[p].l+tree[p].r&gt;&gt;<span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span>(loc&lt;=mid)<span class="built_in">equal</span>(p&lt;&lt;<span class="number">1</span>,loc,val);</span><br><span class="line"><span class="keyword">else</span> <span class="built_in">equal</span>(p&lt;&lt;<span class="number">1</span>|<span class="number">1</span>,loc,val);</span><br><span class="line"><span class="built_in">pushup</span>(p);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">query</span><span class="params">(<span class="type">int</span> p,<span class="type">int</span> L,<span class="type">int</span> R)</span></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(L&lt;=tree[p].l&amp;&amp;tree[p].r&lt;=R)<span class="keyword">return</span> tree[p].val;</span><br><span class="line"><span class="type">int</span> mid=tree[p].l+tree[p].r&gt;&gt;<span class="number">1</span>,ans=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">if</span>(L&lt;=mid)ans+=<span class="built_in">query</span>(p&lt;&lt;<span class="number">1</span>,L,R);</span><br><span class="line"><span class="keyword">if</span>(mid&lt;R)ans+=<span class="built_in">query</span>(p&lt;&lt;<span class="number">1</span>|<span class="number">1</span>,L,R);</span><br><span class="line"><span class="keyword">return</span> ans;</span><br><span class="line">&#125;</span><br><span class="line">&#125;tree[<span class="number">2</span>];</span><br><span class="line"><span class="type">char</span> s[<span class="number">500010</span>];<span class="type">int</span> a[<span class="number">500010</span>];</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="type">int</span> n=<span class="built_in">read</span>(),q=<span class="built_in">read</span>();</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=n;i++)cin&gt;&gt;s[i];</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=n;i++)a[i]=s[i]<span class="number">-48</span>;</span><br><span class="line">tree[<span class="number">1</span>].<span class="built_in">build</span>(<span class="number">1</span>,<span class="number">0</span>,n<span class="number">+10</span>),tree[<span class="number">0</span>].<span class="built_in">build</span>(<span class="number">1</span>,<span class="number">0</span>,n<span class="number">+10</span>);</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">2</span>;i&lt;=n;i++)<span class="keyword">if</span>(a[i]==a[i<span class="number">-1</span>])tree[<span class="number">1</span>].<span class="built_in">equal</span>(<span class="number">1</span>,i,<span class="number">1</span>);</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=q;i++)&#123;</span><br><span class="line"><span class="type">int</span> op=<span class="built_in">read</span>(),l=<span class="built_in">read</span>(),r=<span class="built_in">read</span>();</span><br><span class="line"><span class="keyword">if</span>(op==<span class="number">1</span>)&#123;</span><br><span class="line">tree[<span class="number">0</span>].<span class="built_in">modify</span>(<span class="number">1</span>,l,<span class="number">1</span>),tree[<span class="number">0</span>].<span class="built_in">modify</span>(<span class="number">1</span>,r<span class="number">+1</span>,<span class="number">-1</span>);</span><br><span class="line"><span class="type">int</span> p1=(tree[<span class="number">0</span>].<span class="built_in">query</span>(<span class="number">1</span>,<span class="number">0</span>,l<span class="number">-1</span>)%<span class="number">2</span>+a[l<span class="number">-1</span>])%<span class="number">2</span>,</span><br><span class="line">p2=(tree[<span class="number">0</span>].<span class="built_in">query</span>(<span class="number">1</span>,<span class="number">0</span>,l)%<span class="number">2</span>+a[l])%<span class="number">2</span>,</span><br><span class="line">p3=(tree[<span class="number">0</span>].<span class="built_in">query</span>(<span class="number">1</span>,<span class="number">0</span>,r)%<span class="number">2</span>+a[r])%<span class="number">2</span>,</span><br><span class="line">p4=(tree[<span class="number">0</span>].<span class="built_in">query</span>(<span class="number">1</span>,<span class="number">0</span>,r<span class="number">+1</span>)%<span class="number">2</span>+a[r<span class="number">+1</span>])%<span class="number">2</span>;</span><br><span class="line"><span class="keyword">if</span>(l&gt;<span class="number">1</span>)&#123;</span><br><span class="line"><span class="keyword">if</span>(p1!=p2)tree[<span class="number">1</span>].<span class="built_in">equal</span>(<span class="number">1</span>,l,<span class="number">0</span>);</span><br><span class="line"><span class="keyword">else</span> tree[<span class="number">1</span>].<span class="built_in">equal</span>(<span class="number">1</span>,l,<span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(r&lt;n)&#123;</span><br><span class="line"><span class="keyword">if</span>(p3!=p4)tree[<span class="number">1</span>].<span class="built_in">equal</span>(<span class="number">1</span>,r<span class="number">+1</span>,<span class="number">0</span>);</span><br><span class="line"><span class="keyword">else</span> tree[<span class="number">1</span>].<span class="built_in">equal</span>(<span class="number">1</span>,r<span class="number">+1</span>,<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">else</span>&#123;</span><br><span class="line"><span class="keyword">if</span>(l==r)<span class="built_in">puts</span>(<span class="string">&quot;Yes&quot;</span>);</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span>(tree[<span class="number">1</span>].<span class="built_in">query</span>(<span class="number">1</span>,l<span class="number">+1</span>,r))<span class="built_in">puts</span>(<span class="string">&quot;No&quot;</span>);</span><br><span class="line"><span class="keyword">else</span> <span class="built_in">puts</span>(<span class="string">&quot;Yes&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;想到一种和其他题解不一样的做法，就写一下吧。&lt;/p&gt;
&lt;h2 id=&quot;Solution：&quot;&gt;&lt;a href=&quot;#Solution：&quot; class=&quot;headerlink&quot; title=&quot;Solution：&quot;&gt;&lt;/a&gt;Solution：&lt;/h2&gt;&lt;p&gt;设设个序列为 $S$，如</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="线段树" scheme="https://akioi.dev/tags/%E7%BA%BF%E6%AE%B5%E6%A0%91/"/>
    
    <category term="差分" scheme="https://akioi.dev/tags/%E5%B7%AE%E5%88%86/"/>
    
  </entry>
  
  <entry>
    <title>题解 [ABC319D] Minimum Width</title>
    <link href="https://akioi.dev/2023/09/09/abc319d-minimum-width/"/>
    <id>https://akioi.dev/2023/09/09/abc319d-minimum-width/</id>
    <published>2023-09-09T23:27:58.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>本题考虑使用二分答案。</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>关于本题单调性的证明：因为显示器的宽度越大，一行能显示的宽度越多，所以显示需要的行数越少（单词总量不变）。所以显示器的宽度和显示需要的行数<strong>具有单调递减的关系</strong>，所以可以使用二分。</p><p>二分枚举显示器的宽度 $w$，然后计算<strong>以 $w$ 为宽度显示单词需要的最少行数</strong>，如果需要的行数小于等于 $m$，则符合要求，否则不符合要求。</p><p>怎么计算呢？</p><p>如果显示器的宽度 $w$ 小于单词的最大宽度 $mw$，说明一个单词都无法放进显示器中，显然是不符合要求的。</p><p>令 $sum$ 表示当前行已经用了多少宽度，$cnt$ 表示当前用了多少行，一次枚举单词的长度 $l_i$，如果当前宽度加上一个空格和 $l_i$ 的长度大于 $w$，说明当前行已经放不下这个单词了，需要新开一行，让 $cnt$ 加 $1$，并且让 $sum$ 等于 $l_i$，否则 $sum$ 加上 $l_i$ 和一个空格的长度。</p><p>时间复杂度：二分的复杂度是 $O(\log n)$，计算一遍的复杂度是 $O(n)$，整体时间复杂度 $O(n \log n)$。 </p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> int long long</span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> l[<span class="number">1000010</span>],n,m,p,mw;</span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">check</span><span class="params">(<span class="type">int</span> w)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(w&lt;mw)<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"><span class="type">int</span> cnt=<span class="number">1</span>,sum=<span class="number">0</span>;</span><br><span class="line">sum=l[<span class="number">1</span>];</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">2</span>;i&lt;=n;i++)&#123;</span><br><span class="line"><span class="keyword">if</span>(sum+l[i]<span class="number">+1</span>&gt;w)sum=l[i],cnt++;</span><br><span class="line"><span class="keyword">else</span> sum+=l[i]<span class="number">+1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> cnt&lt;=m;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">signed</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">cin&gt;&gt;n&gt;&gt;m;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=n;i++)cin&gt;&gt;l[i],mw=<span class="built_in">max</span>(mw,l[i]);</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=(<span class="number">1LL</span>&lt;&lt;<span class="number">62</span>);i;i&gt;&gt;=<span class="number">1</span>)<span class="keyword">if</span>(!<span class="built_in">check</span>(p+i))p+=i;</span><br><span class="line">cout&lt;&lt;p<span class="number">+1LL</span>&lt;&lt;endl;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;本题考虑使用二分答案。&lt;/p&gt;
&lt;h2 id=&quot;思路&quot;&gt;&lt;a href=&quot;#思路&quot; class=&quot;headerlink&quot; title=&quot;思路&quot;&gt;&lt;/a&gt;思路&lt;/h2&gt;&lt;p&gt;关于本题单调性的证明：因为显示器的宽度越大，一行能显示的宽度越多，所以显示需要的行数越少（单词总量不变</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="二分" scheme="https://akioi.dev/tags/%E4%BA%8C%E5%88%86/"/>
    
  </entry>
  
  <entry>
    <title>题解 P3135 [USACO16JAN] Fort Moo P</title>
    <link href="https://akioi.dev/2023/08/19/p3135-usaco16jan-fort-moo/"/>
    <id>https://akioi.dev/2023/08/19/p3135-usaco16jan-fort-moo/</id>
    <published>2023-08-19T04:44:34.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>我提供一种奇特的解法。</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><h3 id="暴力"><a href="#暴力" class="headerlink" title="暴力"></a>暴力</h3><p>枚举左上角坐标 $(x_1,y_1)$ 和右上角坐标 $(x_2,y_2)$ ，然后用二维前缀和判断一下有没有沼泽地，最后算一下面积，取最大值 就是答案。</p><p>时间复杂度 $O(n^4)$ ，很明显会超时。</p><p>暴力代码：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> sum[<span class="number">1145</span>][<span class="number">1145</span>];</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">query</span><span class="params">(<span class="type">int</span> x1,<span class="type">int</span> y1,<span class="type">int</span> x2,<span class="type">int</span> y2)</span></span>&#123;</span><br><span class="line"><span class="keyword">return</span> sum[x2][y2]-sum[x1<span class="number">-1</span>][y2]-sum[x2][y1<span class="number">-1</span>]+sum[x1<span class="number">-1</span>][y1<span class="number">-1</span>];</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="type">int</span> n,m;</span><br><span class="line">cin&gt;&gt;n&gt;&gt;m;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=n;i++)&#123;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> j=<span class="number">1</span>;j&lt;=m;j++)&#123;</span><br><span class="line"><span class="type">char</span> s;</span><br><span class="line">cin&gt;&gt;s;</span><br><span class="line">sum[i][j]=-sum[i<span class="number">-1</span>][j<span class="number">-1</span>]+sum[i<span class="number">-1</span>][j]+sum[i][j<span class="number">-1</span>]+(s==<span class="string">&#x27;X&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">int</span> ans=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> x1=<span class="number">1</span>;x1&lt;=n;x1++)&#123;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> y1=<span class="number">1</span>;y1&lt;=m;y1++)&#123;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> x2=x1;x2&lt;=n;x2++)&#123;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> y2=y1;y2&lt;=m;y2++)&#123;</span><br><span class="line"><span class="keyword">if</span>(x1==x2&amp;&amp;y1==y2||<span class="built_in">query</span>(x1,y1,x2,y1)||<span class="built_in">query</span>(x1,y1,x1,y2)||<span class="built_in">query</span>(x2,y1,x2,y2)||<span class="built_in">query</span>(x1,y2,x2,y2))<span class="keyword">continue</span>;</span><br><span class="line">ans=<span class="built_in">max</span>(ans,(x2-x1<span class="number">+1</span>)*(y2-y1<span class="number">+1</span>));</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;ans&lt;&lt;endl;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="优化"><a href="#优化" class="headerlink" title="优化"></a>优化</h3><p>我们可以枚举一个矩形的两列竖边 $l_1$ 和 $l_2$ ，然后枚举所有在 $[l_1,l_2]$ 间没有沼泽的横边，处理出来放到一个数组 $q$ 里，如图</p><p>我们已经保证横边没有沼泽了，我们还需要找出两条横边，且两条横边夹着的两条竖边间没有沼泽，这样就能求出矩形的面积，然后取最大值。</p><p>问题是我们要找出两条横边并且是复杂度是 $O(n)$ 的，怎么找？</p><p>定义两个指针 $p_1$ 和 $p_2$ ，遍历一下数组 $q$ ，令当前下标为 $i$ ，让 $p_2$ 等于 $i$ ，如果 $p_1$ 到 $p_2$ 间有沼泽，令 $p_1$ 等于 $p_2$ ，否则不变，计算此时的面积，取最大值。</p><p>关于这样做正确性证明：如果能走到 $[p_1,p_2-1]$ 这里，那么 $[p_1,p_2-1]$ 之间肯定是没有沼泽的，如果在 $[p_1,p_2]$ 间发现了沼泽，那么沼泽肯定是在 $[p_{2}-1,p_2]$ 之间的，也就是说区间想以 $p_2$ 结尾，开头肯定只能从 $p_2$ 开始。</p><p>时间复杂度 $O(n^3)$ 。</p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> sum[<span class="number">1145</span>][<span class="number">1145</span>],q[<span class="number">1145</span>];</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">query</span><span class="params">(<span class="type">int</span> x1,<span class="type">int</span> y1,<span class="type">int</span> x2,<span class="type">int</span> y2)</span></span>&#123;</span><br><span class="line"><span class="keyword">return</span> sum[x2][y2]-sum[x1<span class="number">-1</span>][y2]-sum[x2][y1<span class="number">-1</span>]+sum[x1<span class="number">-1</span>][y1<span class="number">-1</span>];</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="type">int</span> n,m;</span><br><span class="line">cin&gt;&gt;n&gt;&gt;m;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=n;i++)&#123;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> j=<span class="number">1</span>;j&lt;=m;j++)&#123;</span><br><span class="line"><span class="type">char</span> s;</span><br><span class="line">cin&gt;&gt;s;</span><br><span class="line">sum[i][j]=-sum[i<span class="number">-1</span>][j<span class="number">-1</span>]+sum[i<span class="number">-1</span>][j]+sum[i][j<span class="number">-1</span>]+(s==<span class="string">&#x27;X&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">int</span> ans=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> l1=<span class="number">1</span>;l1&lt;=m;l1++)&#123;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> l2=l1;l2&lt;=m;l2++)&#123;</span><br><span class="line"><span class="type">int</span> st,ed,p=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> l3=<span class="number">1</span>;l3&lt;=n;l3++)&#123;</span><br><span class="line"><span class="keyword">if</span>(!<span class="built_in">query</span>(l3,l1,l3,l2))q[++p]=l3; <span class="comment">//预处理合法的横边</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(p==<span class="number">0</span>)<span class="keyword">continue</span>;</span><br><span class="line">st=ed=q[<span class="number">1</span>];</span><br><span class="line">ans=<span class="built_in">max</span>(ans,(ed-st<span class="number">+1</span>)*(l2-l1<span class="number">+1</span>));</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=p;i++)&#123;</span><br><span class="line">ed=q[i];</span><br><span class="line"><span class="keyword">if</span>(<span class="built_in">query</span>(st,l1,ed,l1)||<span class="built_in">query</span>(st,l2,ed,l2))&#123;</span><br><span class="line">st=ed; <span class="comment">//如果[p1,p2]有沼泽，那么p1=p2</span></span><br><span class="line">ans=<span class="built_in">max</span>(ans,(ed-st<span class="number">+1</span>)*(l2-l1<span class="number">+1</span>));</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> ans=<span class="built_in">max</span>(ans,(ed-st<span class="number">+1</span>)*(l2-l1<span class="number">+1</span>)); <span class="comment">//否则可以走过来，不变</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;ans&lt;&lt;endl;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;我提供一种奇特的解法。&lt;/p&gt;
&lt;h2 id=&quot;思路&quot;&gt;&lt;a href=&quot;#思路&quot; class=&quot;headerlink&quot; title=&quot;思路&quot;&gt;&lt;/a&gt;思路&lt;/h2&gt;&lt;h3 id=&quot;暴力&quot;&gt;&lt;a href=&quot;#暴力&quot; class=&quot;headerlink&quot; title=&quot;暴力</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="二维前缀和" scheme="https://akioi.dev/tags/%E4%BA%8C%E7%BB%B4%E5%89%8D%E7%BC%80%E5%92%8C/"/>
    
    <category term="双指针" scheme="https://akioi.dev/tags/%E5%8F%8C%E6%8C%87%E9%92%88/"/>
    
  </entry>
  
  <entry>
    <title>题解 P5202 [USACO19JAN] Redistricting P</title>
    <link href="https://akioi.dev/2023/08/08/p5202-usaco19jan-redistricting/"/>
    <id>https://akioi.dev/2023/08/08/p5202-usaco19jan-redistricting/</id>
    <published>2023-08-08T02:04:24.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>首先我们思考朴素的 dp 方程。</p><h3 id="定义状态"><a href="#定义状态" class="headerlink" title="定义状态"></a>定义状态</h3><p>首先定义 $dp_i$，表示当前最后一个分区是以 $i$ 结尾时均势区和更赛牛较多区的和的最小值。</p><p>然后我们定义 $cnt_i$ 表示 $[1,i]$ 范围内更赛牛减荷斯坦牛的数量，所以 $[l,r]$ 范围内更赛牛减荷斯坦牛的数量就是 $cnt_r - cnt_{l-1}$，在读入时只需要碰到字符 G 加 $1$，碰到字符 H 减 $1$ 就可以了。</p><h3 id="转移方程"><a href="#转移方程" class="headerlink" title="转移方程"></a>转移方程</h3><p>我们假设倒数第二个区间是以 $j$ 结尾的，则最后一个区间的范围是 $[j+1,i]$。由于一个区间的长度大于 $1$ 小于 $k$，所以 $j$ 的范围是从 $i-k$ 到 $i-1$。枚举每一个 $j$，如果 $sum_i-sum_j\geqslant0$，也就是说 $[j+1,i]$ 这个区间是一个均势区或更赛牛较多区，$dp_i&#x3D;dp_j+1$，否则这不是均势区或更赛牛较多区，$dp_i&#x3D;dp_j$，最后对所有的 $j$ 转移来的情况区最小值，方程如下：</p><p>$$dp_i&#x3D;\min\limits_{j&#x3D;i-k}^{i-1} \begin{cases}dp_j+1&amp;sum_i-sum_j\geqslant0\dp_j&amp;sum_i-sum_j &lt;0\end{cases}$$</p><p>时间复杂度 $\mathcal{O}(nk)$。</p><h3 id="优化"><a href="#优化" class="headerlink" title="优化"></a>优化</h3><p>很显然，这样一定会 TLE。</p><p>我们从状态转移处下手。由于每次转移的范围 $k$ 是固定的，所以没必要一个一个枚举 $j$，而可以用单调队列维护这段转移区间。队列内部存放决策的下标 $j$。</p><p>设 $f$ 为当前队首的值， $b$ 为当前队尾的值，则转移分三步：</p><p>如果 $i - f &gt; k$ 且队列不为空，说明它超过了长度限制，不能从这里转移来，从队首弹出。循环弹出所有过期的。</p><p>转移 $dp_i$ 时，从 $dp_f$ 转移来，这时是最优的。</p><p>循环从队尾弹出过期时间早且不够优秀的。</p><p>什么叫“不够优秀”？</p><p>第一种情况，如果 $dp_b &gt; dp_i$，那么从 $dp_b$ 转移不如 $dp_i$，弹出；第二种情况，如果 $dp_b &#x3D; dp_i$，但是 $sum_i - sum_j \geqslant 0$，转移时需要加上 $1$，这样最多和 $dp_i$ 转移答案相同，或不及 $dp_i$，且比 $dp_i$ 过期得早，弹出。</p><p>核心代码如下：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span>(!q.<span class="built_in">empty</span>()&amp;&amp;i-q.<span class="built_in">front</span>()&gt;k)q.<span class="built_in">pop_front</span>();</span><br><span class="line"><span class="type">int</span> j=q.<span class="built_in">front</span>();</span><br><span class="line"><span class="keyword">if</span>(cnt[i]-cnt[j]&gt;=<span class="number">0</span>)dp[i]=dp[j]<span class="number">+1</span>;</span><br><span class="line"><span class="keyword">else</span> dp[i]=dp[j];</span><br><span class="line"><span class="keyword">while</span>(!q.<span class="built_in">empty</span>()&amp;&amp;(dp[q.<span class="built_in">back</span>()]&gt;dp[i]||(dp[q.<span class="built_in">back</span>()]==dp[i]&amp;&amp;cnt[i]-cnt[q.<span class="built_in">back</span>()]&gt;=<span class="number">0</span>)))q.<span class="built_in">pop_back</span>();</span><br><span class="line">q.<span class="built_in">push_back</span>(i);</span><br></pre></td></tr></table></figure><p>时间复杂度 $\mathcal{O}(n)$ 。</p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">char</span> s[<span class="number">3</span>*<span class="number">114514</span>];</span><br><span class="line"><span class="type">int</span> cnt[<span class="number">3</span>*<span class="number">114514</span>],dp[<span class="number">3</span>*<span class="number">114514</span>];</span><br><span class="line">deque&lt;<span class="type">int</span>&gt;q;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="type">int</span> n,k;</span><br><span class="line">cin&gt;&gt;n&gt;&gt;k;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%s&quot;</span>,s<span class="number">+1</span>);</span><br><span class="line">q.<span class="built_in">push_back</span>(<span class="number">0</span>);</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=n;i++)&#123;</span><br><span class="line"><span class="keyword">if</span>(s[i]==<span class="string">&#x27;G&#x27;</span>)cnt[i]=cnt[i<span class="number">-1</span>]<span class="number">+1</span>;</span><br><span class="line"><span class="keyword">else</span> cnt[i]=cnt[i<span class="number">-1</span>]<span class="number">-1</span>;</span><br><span class="line"><span class="keyword">while</span>(!q.<span class="built_in">empty</span>()&amp;&amp;i-q.<span class="built_in">front</span>()&gt;k)q.<span class="built_in">pop_front</span>();</span><br><span class="line"><span class="type">int</span> j=q.<span class="built_in">front</span>();</span><br><span class="line"><span class="keyword">if</span>(cnt[i]-cnt[j]&gt;=<span class="number">0</span>)dp[i]=dp[j]<span class="number">+1</span>;</span><br><span class="line"><span class="keyword">else</span> dp[i]=dp[j];</span><br><span class="line"><span class="keyword">while</span>(!q.<span class="built_in">empty</span>()&amp;&amp;(dp[q.<span class="built_in">back</span>()]&gt;dp[i]||(dp[q.<span class="built_in">back</span>()]==dp[i]&amp;&amp;cnt[i]-cnt[q.<span class="built_in">back</span>()]&gt;=<span class="number">0</span>)))q.<span class="built_in">pop_back</span>();</span><br><span class="line">q.<span class="built_in">push_back</span>(i);</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;dp[n]&lt;&lt;endl;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;思路&quot;&gt;&lt;a href=&quot;#思路&quot; class=&quot;headerlink&quot; title=&quot;思路&quot;&gt;&lt;/a&gt;思路&lt;/h2&gt;&lt;p&gt;首先我们思考朴素的 dp 方程。&lt;/p&gt;
&lt;h3 id=&quot;定义状态&quot;&gt;&lt;a href=&quot;#定义状态&quot; class=&quot;headerlink&quot; </summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="动态规划" scheme="https://akioi.dev/tags/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/"/>
    
    <category term="单调队列" scheme="https://akioi.dev/tags/%E5%8D%95%E8%B0%83%E9%98%9F%E5%88%97/"/>
    
  </entry>
  
  <entry>
    <title>题解 P9460 众数 I</title>
    <link href="https://akioi.dev/2023/07/16/p9460-mode-i/"/>
    <id>https://akioi.dev/2023/07/16/p9460-mode-i/</id>
    <published>2023-07-16T14:24:58.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>题目中</p><blockquote><p>你需要求出有多少整数可能成为 $b$ 的<strong>众数</strong>。</p></blockquote><p>想表达的意思应该是</p><blockquote><p>你需要求出有多少种数可能成为 $b$ 的<strong>众数</strong>。</p></blockquote><p>吧。</p><p>所以你输出的是能成为众数的<strong>种类数</strong>，而不是个数。</p><h2 id="解法："><a href="#解法：" class="headerlink" title="解法："></a>解法：</h2><p>这里我提供一种贪心的做法。</p><p>首先只需维护出每一种数出现的次数（因为题目只关心可能成为众数的数的数量）。</p><p>接下来我们思考怎样一种数才可能成为众数。</p><p>经过 $k$ 次修改以后，一种数只有在<strong>被修改后出现次数大于等于被修改后出现次数最大的那种数的出现次数</strong>时才可以成为众数。</p><p>那么每一次修改是什么呢？</p><p>想要让第 $i$ 种数成为众数，对于每一次修改，我们将除了<strong>第 $i$ 种</strong>数外的<strong>一个</strong>数修改为<strong>第 $i$ 种</strong>数。这样就让<strong>第 $i$ 种数</strong>出现的次数 $+1$ ，让除了<strong>第 $i$ 种</strong>数外的<strong>一种数</strong>出现的次数 $-1$ 。不难想到，这样可以让第 $i$ 种数出现的次数最大。</p><p>具体来说，设第 $i$ 种数出现的次数为 $v_i$ ，那么它在被操作 $k$ 次后出现的次数为 $v_i+k$ ，设经过操作后的最大出现次数为 $x$ ，那么第 $i$ 种数能成为众数的条件是：</p><p>$$v_i+k \geq x$$</p><p><strong>因为 $v_i+k$ 已经确定了，所以想让成为众数的数尽可能多，就要让 $x$ 最小。</strong></p><p>怎么让 $x$ 最小呢？</p><p>我们让当前一个最大的出现次数 $-1$ ，然后把它放回原数列，再找到当前一个最大的出现次数，如此操作 $k$ 次就可以了。</p><p>比如一个数组 $v&#x3D;[1,2,3,5,4,3]$ ，经过 $5$ 次操作后的状态如下：</p><p>第一次操作：</p><p>$$[1,2,3,4,4,3]$$</p><p>第二次操作：</p><p>$$[1,2,3,3,4,3]$$</p><p>第三次操作：</p><p>$$[1,2,3,3,3,3]$$</p><p>第四次操作：</p><p>$$[1,2,2,3,3,3]$$</p><p>第五次操作：</p><p>$$[1,2,2,2,3,3]$$</p><p>由于每次都要取出其中的最大值，所以这个问题刚好可以用大根堆（优先队列）来解决。每次操作取出堆顶，将其 $-1$ ，然后丢回堆里面。</p><p>核心代码如下：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">priority_queue&lt;<span class="type">int</span>&gt;q;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=tot;i++)&#123;</span><br><span class="line">q.<span class="built_in">push</span>(v[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span>(k--)&#123;</span><br><span class="line"><span class="type">int</span> tmp=q.<span class="built_in">top</span>()<span class="number">-1</span>;</span><br><span class="line">q.<span class="built_in">pop</span>();</span><br><span class="line">q.<span class="built_in">push</span>(tmp);</span><br><span class="line">&#125;</span><br><span class="line">tmp=q.<span class="built_in">top</span>();</span><br></pre></td></tr></table></figure><p>由于堆每次操作的复杂度为 $O(\log n)$ ，$k$ 次操作的复杂度就是 $O(k \log n)$ ，也就是 $O(n \log n)$ ，在 $10^6$ 的数据下可以通过。</p><p>最后一个问题，怎么处理无限多种数可以成为众数的情况？</p><p><strong>如果经过操作后的最大出现次数 $x \leq k$ 时，也就是说任意一个数操作 $k$ 次都能修改成众数，自然答案就是无限了。</strong></p><h2 id="代码如下（写的不太好）："><a href="#代码如下（写的不太好）：" class="headerlink" title="代码如下（写的不太好）："></a>代码如下（写的不太好）：</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> int long long</span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> cnt[<span class="number">1919810</span>],v[<span class="number">1919810</span>];</span><br><span class="line">priority_queue&lt;<span class="type">int</span>&gt;q;</span><br><span class="line"><span class="type">int</span> n,k,tot;</span><br><span class="line"><span class="function"><span class="type">signed</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line">cin&gt;&gt;n&gt;&gt;k;</span><br><span class="line"><span class="type">int</span> vk=k;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=n;i++)&#123;</span><br><span class="line"><span class="type">int</span> x;</span><br><span class="line">cin&gt;&gt;x;</span><br><span class="line">cnt[x]++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=n;i++)&#123;</span><br><span class="line"><span class="keyword">if</span>(cnt[i])v[++tot]=cnt[i];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=tot;i++)&#123;</span><br><span class="line">q.<span class="built_in">push</span>(v[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">int</span> mx=q.<span class="built_in">top</span>();</span><br><span class="line"><span class="keyword">while</span>(k--)&#123;</span><br><span class="line"><span class="type">int</span> x=q.<span class="built_in">top</span>()<span class="number">-1</span>;</span><br><span class="line">q.<span class="built_in">pop</span>();</span><br><span class="line">q.<span class="built_in">push</span>(x);</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">int</span> ww=q.<span class="built_in">top</span>(),ans=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">if</span>(ww&lt;=vk)&#123;</span><br><span class="line">    cout&lt;&lt;<span class="string">&quot;pigstd&quot;</span>&lt;&lt;endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=tot;i++)&#123;</span><br><span class="line"><span class="keyword">if</span>(v[i]+vk&gt;=ww)&#123;</span><br><span class="line">ans++;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;ans&lt;&lt;endl;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;题目中&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;你需要求出有多少整数可能成为 $b$ 的&lt;strong&gt;众数&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;想表达的意思应该是&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;你需要求出有多少种数可能成为 $b$ 的&lt;</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="贪心" scheme="https://akioi.dev/tags/%E8%B4%AA%E5%BF%83/"/>
    
  </entry>
  
  <entry>
    <title>CF926C题解</title>
    <link href="https://akioi.dev/2022/07/21/cf926c/"/>
    <id>https://akioi.dev/2022/07/21/cf926c/</id>
    <published>2022-07-21T10:10:30.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>这是一道很简单的模拟。</p><h1 id="解题思路："><a href="#解题思路：" class="headerlink" title="解题思路："></a>解题思路：</h1><p>我们定义两个变量 $cnt1$ $cnt2$，分别用于记录上一个连续 $0&#x2F;1$ 区间的长度和这一个连续 $0&#x2F;1$ 区间的长度。只要这个连续区间的长度不等于上个区间的长度，那么直接输出<code>NO</code>，然后<code>return 0</code>就可以了(因为这里不一样后面就无需判断，这是一个小优化)。如果相等，那么 $cnt2$ 清零，重新计算新的连续区间的长度，以此类推计算就可以了。</p><p>那么这个过程怎么实现呢？</p><p>对于代码实现来说，对于当前的 $a_i$ 来说，分两种情况：</p><ul><li><p>如果 $a_i$ 等于 $a_{i-1}$ ，那么说明还在当前的区间中，那么 $cnt2+1$ ，长度加 $1$ 。</p></li><li><p>如果 $a_i$ 不等于 $a_{i-1}$ ，那么按照上面的思路判断就可以了。</p></li></ul><p>这里需要注意一些细节：加一个特判，判断 $cnt1$ 是不是 $0$ ，并在<code>cnt2=1</code>前面把 $cnt1$ 修改为 $cnt2$ ，就可以了。然后把 $a_{n+1}$ 赋值为 $2$ ，循环到 $n+1$ 就可以处理最后一次的问题。</p><p>ps：一定要从 $2$ 开始循环，要不然会出问题，为什么呢？</p><p>因为从 $1$ 开始循环，那么 $a_0$ 的值始终是 $0$ ，我们无法确定 $a_1$ 是零是一，这样就会造成 $cnt$ 错误。</p><p>如果大家还是看的不清楚，可以看代码里的注释。</p><h1 id="Code"><a href="#Code" class="headerlink" title="Code:"></a>Code:</h1><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">a[n<span class="number">+1</span>]=<span class="number">2</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>;i&lt;=n;i++)&#123;</span><br><span class="line">cin&gt;&gt;a[i];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">2</span>;i&lt;=n<span class="number">+1</span>;i++)&#123;</span><br><span class="line"><span class="keyword">if</span>(a[i]==a[i<span class="number">-1</span>])&#123;  <span class="comment">//如果和上一个数字相同</span></span><br><span class="line">cnt2++; <span class="comment">//说明这个区间还没有结束，长度++</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span>&#123; <span class="comment">//不相同</span></span><br><span class="line"><span class="keyword">if</span>(cnt2!=cnt1&amp;&amp;cnt1)&#123;   <span class="comment">//与上次长度不相同且不是第一次计数</span></span><br><span class="line">cout&lt;&lt;<span class="string">&quot;NO&quot;</span>&lt;&lt;endl;   <span class="comment">//NO</span></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line">cnt1=cnt2;    <span class="comment">//长度赋值，防止出现第一次cnt1=0的情况</span></span><br><span class="line">cnt2=<span class="number">1</span>;   <span class="comment">//长度清空为1，因为这是新区间的第一个数</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;<span class="string">&quot;YES&quot;</span>&lt;&lt;endl;</span><br></pre></td></tr></table></figure><p>这个写法应该是目前特判比较少的解法了吧。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;这是一道很简单的模拟。&lt;/p&gt;
&lt;h1 id=&quot;解题思路：&quot;&gt;&lt;a href=&quot;#解题思路：&quot; class=&quot;headerlink&quot; title=&quot;解题思路：&quot;&gt;&lt;/a&gt;解题思路：&lt;/h1&gt;&lt;p&gt;我们定义两个变量 $cnt1$ $cnt2$，分别用于记录上一个连续 $0&amp;#</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="模拟" scheme="https://akioi.dev/tags/%E6%A8%A1%E6%8B%9F/"/>
    
  </entry>
  
  <entry>
    <title>CF620A题解</title>
    <link href="https://akioi.dev/2022/07/20/cf620a/"/>
    <id>https://akioi.dev/2022/07/20/cf620a/</id>
    <published>2022-07-20T09:37:17.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>update：有一个图挂了，我重新补上，管理求过</p><p>这道题不难，主要考察的是数学知识。</p><h1 id="前铺：欧几里得距离"><a href="#前铺：欧几里得距离" class="headerlink" title="前铺：欧几里得距离"></a>前铺：欧几里得距离</h1><p>首先我们都知道，<strong>两点之间线段最短</strong>，如下图所示：</p><p><img src="https://s1.ax1x.com/2022/07/20/jHD36g.png"></p><p>这个距离很好求，我们把 $A$ 点和 $B$ 所在的轴画出来，如下图所示：</p><p><img src="https://s1.ax1x.com/2022/07/20/jHDDcF.jpg"></p><p>很容易看出来这三条线构成了一个直角三角形。根据勾股定理，我们就求出了距离公式，如下：</p><p>$$\large{dis(i,j)&#x3D;\sqrt{(x_i-x_j)^2 + (y_i-y_j)^2}}$$</p><p>这个距离公式也是现在最常用的距离公式。</p><h1 id="切比雪夫距离"><a href="#切比雪夫距离" class="headerlink" title="切比雪夫距离"></a>切比雪夫距离</h1><p>切比雪夫距离用于解决格点上的距离问题。这类问题只能向自己点的上、下、左、右、左上、左下、右上、右下方向走。</p><p>在这个问题中，每走一个斜线和走一个直线的距离相同。那我们想要距离最短，那就按照欧几里得距离的思想，尽量先走斜线到对方的横坐标上，在走直线到达对方的点，如下图所示：</p><p><img src="https://cdn.luogu.com.cn/upload/image_hosting/jbpbgmpl.png"></p><p>这就是当前问题下的最短距离。</p><p>那么怎么算出距离呢？</p><p>因为棋盘的性质，走一个斜线等于走一个直线的距离，所以只需要求出两边距离的最大值就可以了。公式如下：</p><p>$$\large{dis(i,j)&#x3D;\max(|x_i-x_j|,|y_i-y_j|)}$$</p><p>按照本题的题意，此题为切比雪夫距离。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;update：有一个图挂了，我重新补上，管理求过&lt;/p&gt;
&lt;p&gt;这道题不难，主要考察的是数学知识。&lt;/p&gt;
&lt;h1 id=&quot;前铺：欧几里得距离&quot;&gt;&lt;a href=&quot;#前铺：欧几里得距离&quot; class=&quot;headerlink&quot; title=&quot;前铺：欧几里得距离&quot;&gt;&lt;/a&gt;前铺</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="数学" scheme="https://akioi.dev/tags/%E6%95%B0%E5%AD%A6/"/>
    
    <category term="几何" scheme="https://akioi.dev/tags/%E5%87%A0%E4%BD%95/"/>
    
  </entry>
  
  <entry>
    <title>AT3935题解</title>
    <link href="https://akioi.dev/2022/07/13/abc090b/"/>
    <id>https://akioi.dev/2022/07/13/abc090b/</id>
    <published>2022-07-13T07:53:49.000Z</published>
    <updated>2026-08-21T15:32:11.612Z</updated>
    
    <content type="html"><![CDATA[<p>回文数判断前面几位大佬已经讲的很清楚了，我讲一种新的 STL 做法。</p><p>这里介绍两个函数，<code>reverse()</code>和<code>to_string()</code>。</p><h1 id="to-string-函数"><a href="#to-string-函数" class="headerlink" title="to_string()函数"></a>to_string()函数</h1><p><code>to_string()</code>是在 C++11 中新加入的函数，定义于<code>&lt;string&gt;</code>头文件中。用法为<code>to_string(val)</code>，其中<code>val</code>可以是<code>int,long,long long,unsigned int,unsigned long long,fload,double,long double</code>类型。其作用是将数字转换成字符串。</p><h1 id="reverse-函数"><a href="#reverse-函数" class="headerlink" title="reverse()函数"></a>reverse()函数</h1><p><code>reverse()</code>函数是一个可以翻转数组，<code>string</code>，<code>vector</code>等数据结构的函数，定义于<code>&lt;algorithm&gt;</code>头文件中。用法为<code>reverse(p1,p2)</code>，<code>p1</code>为前指针，<code>p2</code>为后指针。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">reverse</span>(array,array+a_length) <span class="comment">//数组</span></span><br><span class="line"><span class="built_in">reverse</span>(str.<span class="built_in">begin</span>(),str.<span class="built_in">end</span>()) <span class="comment">//string</span></span><br><span class="line"><span class="built_in">reverse</span>(v.<span class="built_in">begin</span>(),v.<span class="built_in">end</span>()) <span class="comment">//vector</span></span><br></pre></td></tr></table></figure><p>明白之后代码就简单多了。</p><h1 id="Code："><a href="#Code：" class="headerlink" title="Code："></a>Code：</h1><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> cnt=<span class="number">0</span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span>&#123;</span><br><span class="line"><span class="type">int</span> l,r;</span><br><span class="line">cin&gt;&gt;l&gt;&gt;r;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i=l;i&lt;=r;i++)&#123;</span><br><span class="line">string s=<span class="built_in">to_string</span>(i);</span><br><span class="line">string ts=s;</span><br><span class="line"><span class="built_in">reverse</span>(s.<span class="built_in">begin</span>(),s.<span class="built_in">end</span>());</span><br><span class="line"><span class="keyword">if</span>(ts==s)&#123;</span><br><span class="line">cnt++;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;cnt&lt;&lt;endl;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;回文数判断前面几位大佬已经讲的很清楚了，我讲一种新的 STL 做法。&lt;/p&gt;
&lt;p&gt;这里介绍两个函数，&lt;code&gt;reverse()&lt;/code&gt;和&lt;code&gt;to_string()&lt;/code&gt;。&lt;/p&gt;
&lt;h1 id=&quot;to-string-函数&quot;&gt;&lt;a href=&quot;#t</summary>
      
    
    
    
    <category term="题解" scheme="https://akioi.dev/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
    <category term="字符串" scheme="https://akioi.dev/tags/%E5%AD%97%E7%AC%A6%E4%B8%B2/"/>
    
    <category term="STL" scheme="https://akioi.dev/tags/STL/"/>
    
  </entry>
  
</feed>
