【第十六屆 藍橋杯 省 C/Python A/Java C 登山】題解

題目鏈接:P12169 [藍橋杯 2025 省 C/Python A/Java C] 登山

思路來源

一開始想的其實是記搜,但是發現還有先找更小的再找更大的這種路徑,所以這樣可能錯過某些最優決策,這樣不行。

于是我又想能不能從最大值出發往回搜,手玩了一下發現其實和記搜沒什么區別,無非是把邊給反向了。

那可能的做法就是強連通分量?我當時板子都掏出來了,但是模擬了一番之后就發現可以用并查集。

下面是正文。

算法:并查集

由于行列是同一套邏輯,所以下面只說同一列內的行操作,同一行內的列操作直接照抄即可。

設現在我們在 ( x , y ) (x, y) (x,y),且存在點 ( i , y ) (i, y) (i,y) 滿足 i > x i > x i>x a i , y < a x , y a_{i, y} < a_{x, y} ai,y?<ax,y?,那么我們可以從 ( x , y ) (x, y) (x,y) ( i , y ) (i, y) (i,y) 連邊表示 ( x , y ) (x, y) (x,y) 可達 ( i , y ) (i, y) (i,y)

那么同理,如果我們在 ( i , y ) (i, y) (i,y),根據題中所說, ( x , y ) (x, y) (x,y) 滿足 x < i x < i x<i a x , y > a i , y a_{x, y} > a_{i, y} ax,y?>ai,y?,同樣可以從 ( i , y ) (i, y) (i,y) ( x , y ) (x, y) (x,y) 連邊。

也就是說,只要存在一個逆序對,就有一對 雙向邊

但是直接 O ( n 2 ) O(n^2) O(n2) 遍歷 O ( m ) O(m) O(m) 次來連邊有點太狂野了,這復雜度也過不去,所以我們開始尋找逆序對連邊的等價命題。

先給出命題:

對于第 j j j 列,設 p r e [ i ] pre[i] pre[i] 表示前 i i i 個元素的最大值, s u f [ i ] suf[i] suf[i] 表示 [ i , n ] [i, n] [i,n] 內元素的最小值,如果 p r e [ i ] > s u f [ i + 1 ] pre[i] > suf[i + 1] pre[i]>suf[i+1],就連一條 ( i , j ) (i, j) (i,j) ( i + 1 , j ) (i + 1, j) (i+1,j) 的邊。

為了方便,做幾點說明。

  • 逆序對連邊生成的邊集為 E 0 E_0 E0?,相鄰連邊生成的邊集為 E 1 E_1 E1?
  • 簡寫 ( l , j ) (l, j) (l,j) ( r , j ) (r, j) (r,j) 連雙向邊為 l ? r l \Longleftrightarrow r l?r

下面證明二者等價。

若有 a l , j > a r , j a_{l, j} > a_{r, j} al,j?>ar,j?,那么有 l ? r l \Longleftrightarrow r l?r,那么對于 i ∈ [ l , r ) i \in [l, r) i[l,r),一定有 p r e [ i ] > s u f [ i + 1 ] pre[i] > suf[i + 1] pre[i]>suf[i+1],那也就是說, E 1 E_1 E1? 會包含 l ? l + 1 , l + 1 ? l + 2 , ? , r ? 1 ? r l \Longleftrightarrow l + 1, \ \ l + 1 \Longleftrightarrow l + 2, \ \ \cdots, \ \ r - 1 \Longleftrightarrow r l?l+1,??l+1?l+2,???,??r?1?r,這相當于包含了一條 l ? r l \Longleftrightarrow r l?r 的雙向邊,所以 E 0 ? E 1 E_0 \subseteq E_1 E0??E1?

若有 p r e [ i ] > s u f [ i + 1 ] pre[i] > suf[i + 1] pre[i]>suf[i+1],那么有 i ? i + 1 i \Longleftrightarrow i + 1 i?i+1,同時,由前綴最大和后綴最小的性質可以得到,必然存在 l ∈ [ 1 , i ] l \in [1, i] l[1,i] r ∈ ( i , n ] r \in (i, n] r(i,n],使得 a l , j > a r , j a_{l, j} > a_{r, j} al,j?>ar,j?,那么首先就有 l ? r l \Longleftrightarrow r l?r。如果 l < i l < i l<i,說明 a l , j > a i , j a_{l, j} > a_{i, j} al,j?>ai,j?,那么由題目條件有 l ? i l \Longleftrightarrow i l?i,同理如果 i + 1 < r i + 1 < r i+1<r,那么 i + 1 ? r i + 1 \Longleftrightarrow r i+1?r,將這三條邊合起來,就包含了一條 i ? i + 1 i \Longleftrightarrow i + 1 i?i+1 的雙向邊,所以 E 1 ? E 0 E_1 \subseteq E_0 E1??E0?

綜上, E 0 = E 1 E_0 = E_1 E0?=E1?,二者等價。

設我們這樣得到了 N N N 個連通塊,第 i i i 個連通塊的大小為 s i z i siz_i sizi?,其塊內最大值為 max ? i \max_i maxi?,則最終答案為

∑ i = 1 N s i z i × m a x i . \sum\limits_{i = 1}^{N}siz_i \times max_i. i=1N?sizi?×maxi?.

時間復雜度 O ( n m ? α ( n m ) ) O(\rm{nm \cdot \alpha(nm)}) O(nm?α(nm))
  • 其中 α ( n m ) \rm{\alpha(nm)} α(nm) 是反阿克曼函數,一般可以看作 3 , 4 3, 4 3,4 左右的常數。
C++ Code
#include <bits/stdc++.h>using i64 = long long;struct DSU {std::vector<int> f, sz;DSU() {}DSU(int n) {init(n);}void init(int n) {f.resize(n);std::iota(f.begin(), f.end(), 0);sz.assign(n, 1);}int find(int x) {while (x != f[x]) {x = f[x] = f[f[x]];}return x;}int size(int x) {return sz[find(x)];}bool merge(int x, int y) {x = find(x);y = find(y);if (x == y) {return false;}sz[x] += sz[y];f[y] = x;return true;}bool same(int x, int y) {return find(x) == find(y);}
};template<class T>
void chmax(T &a, T b) {if (a < b) {a = b;}
}
constexpr int inf = std::numeric_limits<int>::max() / 2;int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout << std::fixed << std::setprecision(6);int n, m;std::cin >> n >> m;const int N = n * m;std::vector<int> a(N);for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {std::cin >> a[i * m + j];}}DSU dsu(N);for (int i = 0; i < n; i++) {std::vector pre(m + 1, 0);std::vector suf(m + 1, inf);for (int j = 0; j < m; j++) {pre[j + 1] = std::max(pre[j], a[i * m + j]);}for (int j = m - 1; j >= 0; j--) {suf[j] = std::min(suf[j + 1], a[i * m + j]);}for (int j = 1; j < m; j++) {if (pre[j] > suf[j]) {dsu.merge(i * m + (j - 1), i * m + j);}}}for (int j = 0; j < m; j++) {std::vector pre(n + 1, 0);std::vector suf(n + 1, inf);for (int i = 0; i < n; i++) {pre[i + 1] = std::max(pre[i], a[i * m + j]);}for (int i = n - 1; i >= 0; i--) {suf[i] = std::min(suf[i + 1], a[i * m + j]);}for (int i = 1; i < n; i++) {if (pre[i] > suf[i]) {dsu.merge((i - 1) * m + j, i * m + j);}}}std::vector max(N, 0);for (int i = 0; i < N; i++) {chmax(max[dsu.find(i)], a[i]);}i64 ans = 0;for (int i = 0; i < N; i++) {if (dsu.find(i) == i) {ans += 1LL * dsu.size(i) * max[i];}}std::cout << 1.* ans / n / m << "\n";return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/77800.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/77800.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/77800.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

軟件工程師中級考試-上午知識點總結(上)

我總結的這些都是每年的考點&#xff0c;必須要記下來的。 1. 計算機系統基礎 1.1 碼 符號位0表示正數&#xff0c;符號位1表示負數。補碼&#xff1a;簡化運算部件的設計&#xff0c;最適合進行數字加減運算。移碼&#xff1a;與前幾種不同&#xff0c;1表示&#xff0c;0表…

Python Cookbook-6.7 有命名子項的元組

任務 Python 元組可以很方便地被用來將信息分組&#xff0c;但是訪問每個子項都需要使用數字索引&#xff0c;所以這種用法有點不便。你希望能夠創建一種可以通過名字屬性訪問的元組。 解決方案 工廠函數是生成符合要求的元組的子類的最簡單方法: #若在2.4中可使用operator…

win10設置軟件開機自啟

參考教程&#xff1a;windows10應用程序設置了開機啟動&#xff0c;但沒有自啟_win10軟件設置了自啟動但是不能自啟動-CSDN博客 主要設置是安全策略&#xff1a;

自注意力機制、多頭自注意力機制、填充掩碼 Python實現

原理講解 【Transformer系列&#xff08;2&#xff09;】注意力機制、自注意力機制、多頭注意力機制、通道注意力機制、空間注意力機制超詳細講解 自注意力機制 import torch import torch.nn as nn# 自注意力機制 class SelfAttention(nn.Module):def __init__(self, input…

【大模型】Browser-Use AI驅動的瀏覽器自動化工具

Browser-Use AI驅動的瀏覽器自動化工具 1. 項目概述2. 核心架構3. 實戰指南3.1 環境安裝3.2 快速啟動3.3 進階功能 4. 常見問題與解決5. 項目優勢與局限6. 擴展資源7. 總結 1. 項目概述 項目地址&#xff1a;browser-use Browser-Use 是一個開源工具&#xff0c;旨在通過 AI 代…

ubuntu20.04安裝安裝x11vnc服務基于gdm3或lightdm這兩種主流的顯示管理器。

前言&#xff1a;在服務端安裝vnc服務&#xff0c;可以方便的遠程操作服務器&#xff0c;而不用非要插上顯示器才行。所以在服務器上安裝vnc是很重要的。在ubuntu20中&#xff0c;默認的顯示管理器已經變為gdm3&#xff0c;它可以帶來與 GNOME 無縫銜接的體驗&#xff0c;強調功…

用銀河麒麟 LiveCD 快速查看原系統 IP 和打印機配置

原文鏈接&#xff1a;用銀河麒麟 LiveCD 快速查看原系統 IP 和打印機配置 Hello&#xff0c;大家好啊&#xff01;今天給大家帶來一篇在銀河麒麟操作系統的 LiveCD 或系統試用鏡像環境下&#xff0c;如何查看原系統中電腦的 IP 地址與網絡打印機 IP 地址的實用教程。在系統損壞…

C++——STL——容器deque(簡單介紹),適配器——stack,queue,priority_queue

目錄 1.deque&#xff08;簡單介紹&#xff09; 1.1 deque介紹&#xff1a; 1.2 deque迭代器底層 1.2.1 那么比如說用迭代器實現元素的遍歷&#xff0c;是如何實現的呢&#xff1f; 1.2.2 頭插 1.2.3 尾插 1.2.4 實現 ?編輯 1.2.5 總結 2.stack 2.1 函數介紹 2.2 模…

Java并發編程-線程池

Java并發編程-線程池 線程池運行原理線程池生命周期線程池的核心參數線程池的阻塞隊列線程池的拒絕策略線程池的種類newFixedThreadPoolnewSingleThreadExecutornewCachedThreadPoolnewScheduledThreadPool 創建線程池jdk的Executors(不建議&#xff0c;會導致OOM)jdk的ThreadP…

【前沿】成像“跨界”測量——掃焦光場成像

01 背景 眼睛是人類認識世界的重要“窗口”&#xff0c;而相機作為眼睛的“延伸”&#xff0c;已經成為生產生活中最常見的工具之一&#xff0c;廣泛應用于工業檢測、醫療診斷與影音娛樂等領域。傳統相機通常以“所見即所得”的方式記錄場景&#xff0c;傳感器捕捉到的二維圖像…

TM1640學習手冊及示例代碼

數據手冊 TM1640數據手冊 數據手冊解讀 這里我們看管腳定義DIN和SCLK&#xff0c;一個數據線一個時鐘線 SEG1~SEG8為段碼&#xff0c;GRID1~GRID16為位碼&#xff08;共陰極情況下&#xff09; 這里VDD給5V 數據指令 數據命令設置 地址命令設置 顯示控制命令 共陰極硬件連接圖…

uni-app 開發企業級小程序課程

課程大小&#xff1a;7.7G 課程下載&#xff1a;https://download.csdn.net/download/m0_66047725/90616393 更多資源下載&#xff1a;關注我 備注&#xff1a;缺少兩個視頻5-14 tabs組件進行基本的數據展示和搜索歷史 處理searchData的刪除操作 1-1導學.mp4 2-10小程序內…

判斷點是否在多邊形內

代碼段解析: const intersect = ((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); 第一部分:(yi > y) !== (yj > y) 作用:檢查點 (x,y) 的垂直位置是否跨越多邊形的當前邊。 yi > y 和 yj > y 分別檢查邊的兩個端…

【redis】集群 如何搭建集群詳解

文章目錄 集群搭建1. 創建目錄和配置2. 編寫 docker-compose.yml完整配置文件 3. 啟動容器4. 構建集群超時 集群搭建 基于 docker 在我們云服務器上搭建出一個 redis 集群出來 當前節點&#xff0c;主要是因為我們只有一個云服務器&#xff0c;搞分布式系統&#xff0c;就比較…

[langchain教程]langchain03——用langchain構建RAG應用

RAG RAG過程 離線過程&#xff1a; 加載文檔將文檔按一定條件切割成片段將切割的文本片段轉為向量&#xff0c;存入檢索引擎&#xff08;向量庫&#xff09; 在線過程&#xff1a; 用戶輸入Query&#xff0c;將Query轉為向量從向量庫檢索&#xff0c;獲得相似度TopN信息將…

C語言復習筆記--字符函數和字符串函數(下)

在上篇我們了解了部分字符函數及字符串函數,下面我們來看剩下的字符串函數. strstr 的使用和模擬實現 老規矩,我們先了解一下strstr這個函數,下面看下這個函數的函數原型. char * strstr ( const char * str1, const char * str2); 如果沒找到就返回NULL指針. 下面我們看下它的…

FreeRTOS中的優先級翻轉問題及其解決方案:互斥信號量詳解

FreeRTOS中的優先級翻轉問題及其解決方案&#xff1a;互斥信號量詳解 在實時操作系統中&#xff0c;任務調度是基于優先級的&#xff0c;高優先級任務應該優先于低優先級任務執行。但在實際應用中&#xff0c;有時會出現"優先級翻轉"的現象&#xff0c;嚴重影響系統…

深度學習-全連接神經網絡

四、參數初始化 神經網絡的參數初始化是訓練深度學習模型的關鍵步驟之一。初始化參數&#xff08;通常是權重和偏置&#xff09;會對模型的訓練速度、收斂性以及最終的性能產生重要影響。下面是關于神經網絡參數初始化的一些常見方法及其相關知識點。 官方文檔參考&#xff1…

GIS開發筆記(9)結合osg及osgEarth實現三維球經緯網格繪制及顯隱

一、實現效果 二、實現原理 按照5的間隔分別創建經緯線的節點,掛在到組合節點,組合節點掛接到根節點。可以根據需要設置間隔度數和線寬、線的顏色。 三、參考代碼 //創建經緯線的節點 osg::Node *GlobeWidget::createGraticuleGeometry(float interval, const osg::Vec4 …

《Relay IR的基石:expr.h 中的表達式類型系統剖析》

TVM Relay源碼深度解讀 文章目錄 TVM Relay源碼深度解讀一 、從Constant看Relay表達式的設計哲學1. 類定義概述2. ConstantNode 詳解1. 核心成員2. 關鍵方法3. 類型系統注冊 3. Constant 詳解1. 核心功能 二. 核心內容概述(1) Relay表達式基類1. RelayExprNode 和 RelayExpr 的…