熙儿爸比 發表於 2025-6-15 15:27:00

2025-6-15模拟测验

<p>自我评价:Tang 完了。</p>
<h1 id="题解">题解</h1>
<p>题解中包含题面描述,但不包含大样例。</p>
<h2 id="t1-怎么又是先增后减why">T1 怎么又是先增后减(why)</h2>
<h3 id="描述">描述</h3>
<p>青蛙又给了周欣一个长为 <span class="math inline">\(N\)</span> 的正整数序列 <span class="math inline">\(A_i\)</span>,周欣可以进行若干次操作,每次可以选择一个位置 <span class="math inline">\(i\)</span>,满足 <span class="math inline">\(1 \leq i \leq N - 1\)</span>,将 <span class="math inline">\(A_i\)</span> 的值和 <span class="math inline">\(A_{i+1}\)</span> 的值进行交换。</p>
<p>设经过这若干次操作后的序列为 <span class="math inline">\(B_i\)</span>,那么需要存在一个整数 <span class="math inline">\(k \in \)</span>,满足:</p>
<ul>
<li>
<p>区间 <span class="math inline">\(\)</span> 构成的子序列 <span class="math inline">\(\)</span> 是一个非严格单调递增的序列,即相邻两项允许相等,但是左边元素不能大于右边元素。</p>
</li>
<li>
<p>区间 <span class="math inline">\(\)</span> 构成的子序列 <span class="math inline">\(\)</span> 是一个非严格单调递减的序列,即相邻两项允许相等,但是左边元素不能小于右边元素。</p>
</li>
</ul>
<p>周欣想知道至少需要对序列进行多少次上述操作后,这个要求才能得以满足,他把这个问题交给了你来解决。</p>
<h3 id="输入">输入</h3>
<p>第一行一个整数 <span class="math inline">\(N\)</span>,表示序列长度。</p>
<p>第二行 <span class="math inline">\(N\)</span> 个整数表示 <span class="math inline">\(A_1,A_2,\cdots,A_N\)</span>。</p>
<h3 id="输出">输出</h3>
<p>输出一个整数,表示答案,即最少的操作次数。</p>
<h3 id="样例">样例</h3>
<p>共 <span class="math inline">\(3\)</span> 组。</p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/786968/galleries/2461545/o_250615070035_%E6%97%A0%E6%A0%87%E9%A2%98.png"></p>
<h3 id="数据范围">数据范围</h3>
<p>对于 <span class="math inline">\(20\%\)</span> 的数据,满足 <span class="math inline">\(N \leq 10\)</span>。</p>
<p>对于 <span class="math inline">\(50\%\)</span> 的数据,满足 <span class="math inline">\(N \leq 5000\)</span>。</p>
<p>对于 <span class="math inline">\(100\%\)</span> 的数据,满足 <span class="math inline">\(1 \leq N \leq 10^5, 1 \leq A_i \leq 10^5\)</span>。</p>
<h3 id="题解-1">题解</h3>
<p>我们令 <span class="math inline">\(x\)</span> 为当前序列中最小的数字。</p>
<p>以样例 <code>3 1 4 1 5 9 2</code> 为例子,<span class="math inline">\(x=1\)</span>(假设为第一个 <span class="math inline">\(1\)</span>)。</p>
<p>我们知道,<span class="math inline">\(x\)</span> 必须被移动到最左边或最右边。样例中,往左移动需要 <span class="math inline">\(1\)</span> 步,但往右移动需要 <span class="math inline">\(4\)</span> 步(不是 <span class="math inline">\(5\)</span> 步,因为相同的 <span class="math inline">\(1\)</span> 不需要交换)。</p>
<p>于是我们得到一个解题思路:</p>
<blockquote>
<p>对于每个数,计算出左边严格比他大的有多少个,记为 <span class="math inline">\(l\)</span>;再计算出右边严格比他大的有多少个,记为 <span class="math inline">\(r\)</span>。然后将 <span class="math inline">\(ans\)</span> 累加 <span class="math inline">\(\min(l,r)\)</span> 即可。</p>
</blockquote>
<p>暴力统计的复杂度为 <span class="math inline">\(\mathcal{O}(n^2)\)</span>,可以得到 <span class="math inline">\(50\%\)</span> 的分数。</p>
<p>使用树状数组优化,复杂度为 <span class="math inline">\(\mathcal{O}(n \log n)\)</span>,可以得到 <span class="math inline">\(100\%\)</span> 的分数。</p>
<pre><code class="language-cpp">#include&lt;bits/stdc++.h&gt;
using namespace std;
inline int read(){
        int x = 0, f = 1;
        char ch = getchar();
        while(!isdigit(ch)){
                if(ch == '-') f = -1;
                ch = getchar();
        }
        while(isdigit(ch)){
                x = (x&lt;&lt;1) + (x&lt;&lt;3) + (ch^48);
                ch = getchar();
        }
        return x * f;
}
const int N = 1e5 + 10;
int n, a, t, LEFT, RIGHT;
inline int lowbit(int x){
        return x &amp; (-x);
}
inline void add(int x){
        while(x &lt;= N){
                t++;
                x += lowbit(x);
        }
        return;
}
inline int query(int x){
        int ans = 0;
        while(x){
                ans += t;
                x -= lowbit(x);
        }
        return ans;
}
signed main(){
        n = read();
        for(int i = 1; i &lt;= n; i++) a = read();
        for(int i = 1; i &lt;= n; i++){
                add(a);
                LEFT = query(N) - query(a);
        }
        memset(t, 0, sizeof(t));
        for(int i = n; i &gt;= 1; i--){
                add(a);
                RIGHT = query(N) - query(a);
        }
        long long ans = 0;
        for(int i = 1; i &lt;= n; i++) ans += min(LEFT, RIGHT);
        cout &lt;&lt; ans &lt;&lt; endl;
        return 0;
}
</code></pre>
<h2 id="t2-美食节festival">T2 美食节(festival)</h2>
<h3 id="描述-1">描述</h3>
<p>在 OI 国,所有城市排成了一个序列,从左往右分布是编号为 <span class="math inline">\(1,2,\cdots,n\)</span> 的城市。</p>
<p>青蛙今天在 OI 国旅游,一开始他在编号为 <span class="math inline">\(x\)</span> 的城市。</p>
<p>OI 国准备举办 <span class="math inline">\(n\)</span> 次美食节,第 <span class="math inline">\(i\)</span> 次的美食节在编号区间 <span class="math inline">\(\)</span> 内的城市上举办。在每次美食节开始之前,青蛙可以在 OI 国中从当前他在的城市旅游到另一个城市,从编号为 <span class="math inline">\(a\)</span> 的城市移动到编号为 <span class="math inline">\(b\)</span> 的城市会让他花费 <span class="math inline">\(|a-b|\)</span> 元钱。</p>
<p>如果一次美食节举办时,青蛙不在美食节举办的范围内,此时我们假设青蛙当前所在城市到美食节举办范围内城市的最短距离为 <span class="math inline">\(k\)</span>,则青蛙会花费 <span class="math inline">\(k\)</span> 元,请人帮他从最近的美食节举办的城市买美食。</p>
<p>为了让青蛙省钱,你需要求出所有的美食节举办结束后,青蛙最少的花费。</p>
<h3 id="输入-1">输入</h3>
<p>第一行两个正整数 <span class="math inline">\(n,x\)</span>。</p>
<p>接下来 <span class="math inline">\(n\)</span> 行,每行两个正整数 <span class="math inline">\(l_i,r_i\)</span>。</p>
<h3 id="输出-1">输出</h3>
<p>输出一个整数,表示答案。</p>
<h3 id="样例-1">样例</h3>
<p>共 <span class="math inline">\(1\)</span> 组。</p>
<p><img src="https://images.cnblogs.com/cnblogs_com/blogs/786968/galleries/2461545/o_250615073535_%E6%97%A0%E6%A0%87%E9%A2%98.png"></p>
<h3 id="数据范围-1">数据范围</h3>
<p>对于 <span class="math inline">\(20\%\)</span> 的数据,满足 <span class="math inline">\(n,x,l_i,r_i \leq 10\)</span>。</p>
<p>对于 <span class="math inline">\(50\%\)</span> 的数据,满足 <span class="math inline">\(n \leq 2000\)</span>。</p>
<p>对于 <span class="math inline">\(100\%\)</span> 的数据,满足 <span class="math inline">\(1 \leq n \leq 5 \times 10^5, 0 \leq x,l_i,r_i \leq 10^9\)</span>。</p>
<h3 id="题解-2">题解</h3>
<p>考虑令 <span class="math inline">\(dp_{i,j}\)</span> 表示第 <span class="math inline">\(i\)</span> 个活动后在 <span class="math inline">\(j\)</span> 的最小疲劳值。</p>
<p>显然的对于每个 <span class="math inline">\(i\)</span>,先赋初始值为 <span class="math inline">\(i-1\)</span> 部分,然后把不在范围内的 <span class="math inline">\(j\)</span> 加上距离作为代价。如果要移动,则使用 <span class="math inline">\(dp_{i,j}+1\)</span> 更新 <span class="math inline">\(dp_{i,j-1}\)</span> 和 <span class="math inline">\(dp_{i,j+1}\)</span>。</p>
<p>然后,我们对于每个 <span class="math inline">\(i\)</span>,把 <span class="math inline">\(dp_{i,j}\)</span> 看成关于 <span class="math inline">\(j\)</span> 的函数。可以证明这个函数最多由 <span class="math inline">\(3\)</span> 个部分组成,斜率分别为 <span class="math inline">\(-1,0,1\)</span>,函数下凸。</p>
<p>于是我们只需要维护最下面的一段即可。令 <span class="math inline">\(l,r\)</span> 代表这段区间的范围,对每个节日动态更新即可,复杂度 <span class="math inline">\(\mathcal{O}(n)\)</span>。</p>
<h4 id="证明">证明</h4>
<p>考虑使用<strong>归纳法</strong>。</p>
<p>当 <span class="math inline">\(i = 0\)</span> 时,<span class="math inline">\(f(j) = |j-x|\)</span>,满足要求。</p>
<p>当 <span class="math inline">\(i\)</span> 增大时,“把不在范围内的 <span class="math inline">\(j\)</span> 加上距离作为代价”部分会使函数加上一个差分为 <span class="math inline">\(-1,0,1\)</span> 的函数,差分变为 <span class="math inline">\(-2,-1,0,1,2\)</span>。</p>
<p>但第二部分计算移动时,会让函数的差分绝对值不超过 <span class="math inline">\(1\)</span>,差分又变成 <span class="math inline">\(-1,0,1\)</span>。</p>
<p>证毕。</p>
<p>代码如下:</p>
<pre><code class="language-cpp">#include&lt;bits/stdc++.h&gt;
#define int long long
using namespace std;
signed main(){
        int n, x; cin &gt;&gt; n &gt;&gt; x;
        int l = x, r = x; //维护下凸函数最下方的区间范围
        int ans = 0;
        for(int i = 1; i &lt;= n; i++){
                int li, ri; cin &gt;&gt; li &gt;&gt; ri;
                if(li &gt; r){
                        ans += li - r;
                        l = r, r = li;
                }else{
                        if(ri &lt; l){
                                ans += l - ri;
                                r = l, l = ri;
                        }else{
                                l = max(l, li);
                                r = min(r, ri);
                        }
                }
        }
        cout &lt;&lt; ans &lt;&lt; endl;
        return 0;
}
</code></pre>
<h2 id="t3-环上合并ring">T3 环上合并(ring)</h2>
<p>咕咕咕。</p><br><br>
来源:https://www.cnblogs.com/zhang-kevin/p/18929612
頁: [1]
查看完整版本: 2025-6-15模拟测验