洛谷P3373線段樹詳解【模板】

洛谷P3373題目概述

洛谷P3373是一道關于線段樹的模板題,題目名稱為“【模板】線段樹 2”。題目的主要要求是對一個長度為 n 的數列進行如下操作:

  1. 將某區間每個數乘上一個數。
  2. 將某區間每個數加上一個數。
  3. 求出某區間所有數的和。

線段樹簡介

線段樹是一種二叉樹數據結構,常用于高效處理區間查詢和更新操作。它可以將一個區間劃分為多個子區間,每個節點代表一個區間,通過維護這些節點的信息,可以在 O ( log ? n ) O(\log n) O(logn) 的時間復雜度內完成區間查詢和更新操作。

代碼詳細講解

1. 頭文件和宏定義
#include <iostream>
#include <cmath>
using namespace std;
#define MAXN 400002
#define lson (root*2)
#define rson (root*2+1)
  • #include <iostream>#include <cmath> 分別引入輸入輸出流和數學庫。
  • using namespace std; 表示使用標準命名空間。
  • MAXN 定義了線段樹數組的最大長度,通常為 4 n 4n 4n,因為線段樹的節點數最多為 4 n 4n 4n
  • lsonrson 分別表示當前節點的左子節點和右子節點的編號。
2. 全局變量
int MOD;
long long sgmt[MAXN], lazy_mul[MAXN], lazy_add[MAXN];
  • MOD 是取模的基數,用于防止結果溢出。
  • sgmt[MAXN] 是線段樹數組,用于存儲每個節點所代表區間的和。
  • lazy_mul[MAXN]lazy_add[MAXN] 是懶標記數組,分別用于標記乘法和加法操作。
3. push_up 函數
void push_up(int root) {sgmt[root] = sgmt[lson] + sgmt[rson];sgmt[root] %= MOD;
}
  • 該函數用于將左右子節點的信息更新到父節點。具體來說,將左子節點和右子節點所代表區間的和相加,并取模后賦值給父節點。
4. push_down 函數
void push_down(int root, int len) {if (lazy_mul[root] == 1 && lazy_add[root] == 0) return;lazy_mul[lson] *= lazy_mul[root], lazy_mul[lson] %= MOD;lazy_mul[rson] *= lazy_mul[root], lazy_mul[rson] %= MOD;lazy_add[lson] *= lazy_mul[root], lazy_add[lson] %= MOD;lazy_add[rson] *= lazy_mul[root], lazy_add[rson] %= MOD;lazy_add[lson] += lazy_add[root], lazy_add[lson] %= MOD;lazy_add[rson] += lazy_add[root], lazy_add[rson] %= MOD;sgmt[lson] *= lazy_mul[root], sgmt[lson] %= MOD;sgmt[lson] += (len/2)*lazy_add[root], sgmt[lson] %= MOD;sgmt[rson] *= lazy_mul[root], sgmt[rson] %= MOD;sgmt[rson] += (len/2)*lazy_add[root], sgmt[rson] %= MOD;lazy_mul[root] = 1, lazy_add[root] = 0;
}
  • 該函數用于將當前節點的懶標記下推到左右子節點。
  • 首先判斷當前節點是否有懶標記,如果 lazy_mul[root] 為 1 且 lazy_add[root] 為 0,則說明沒有懶標記,直接返回。
  • 然后將當前節點的乘法懶標記和加法懶標記下推到左右子節點,并更新左右子節點的線段樹數組和懶標記數組。
  • 最后將當前節點的懶標記重置為初始值。
5. update 函數
void update(int a, int b, long long c, long long d, int l, int r, int root) {if (a <= l && r <= b) {sgmt[root] *= c, sgmt[root] %= MOD;sgmt[root] += (r-l+1)*d, sgmt[root] %= MOD;lazy_mul[root] *= c, lazy_mul[root] %= MOD;lazy_add[root] *= c, lazy_add[root] %= MOD;lazy_add[root] += d, lazy_add[root] %= MOD;return;}push_down(root,r-l+1);int mid = (l+r)/2;if (a <= mid) update(a,b,c,d,l,mid,lson);if (b > mid) update(a,b,c,d,mid+1,r,rson);push_up(root);
}
  • 該函數用于更新區間 [a, b] 內的所有數,將每個數先乘上 c,再加上 d
  • 如果當前節點所代表的區間完全包含在 [a, b] 內,則直接更新當前節點的線段樹數組和懶標記數組。
  • 否則,先將當前節點的懶標記下推,然后遞歸更新左右子節點,最后更新當前節點的線段樹數組。
6. query 函數
long long query(int a, int b, int l, int r, int root) {if (a <= l && r <= b) return sgmt[root];push_down(root,r-l+1);long long ans = 0;int mid = (l+r)/2;if (a <= mid) ans += query(a,b,l,mid,lson), ans %= MOD;if (b > mid) ans += query(a,b,mid+1,r,rson), ans %= MOD;return ans;
}
  • 該函數用于查詢區間 [a, b] 內所有數的和。
  • 如果當前節點所代表的區間完全包含在 [a, b] 內,則直接返回當前節點的線段樹數組的值。
  • 否則,先將當前節點的懶標記下推,然后遞歸查詢左右子節點,并將結果相加。
7. build 函數
void build(int l, int r, int root) {if (l == r) return;int mid = (l+r)/2;build(l,mid,lson);build(mid+1,r,rson);push_up(root);return;
}
  • 該函數用于構建線段樹。
  • 如果當前節點所代表的區間只有一個元素,則直接返回。
  • 否則,遞歸構建左右子節點,然后更新當前節點的線段樹數組。
8. main 函數
int main() {for (int i = 1; i < MAXN; i++)lazy_mul[i] = 1;int n, m; cin >> n >> m >> MOD;int npot = 1 << (int)ceil(log2(n));for (int i = 0; i < n; i++)cin >> sgmt[npot+i];n = npot;int l = 1, r = n, root = 1;build(l,r,root);while (m--) {int op, a, b, c; cin >> op >> a >> b;if (op == 1) {cin >> c; update(a,b,c,0,l,r,root);} else if (op == 2) {cin >> c; update(a,b,1,c,l,r,root);} elsecout << query(a,b,l,r,root)%MOD << endl;}return 0;
}
  • 首先將所有乘法懶標記初始化為 1。
  • 然后讀取數列的長度 n、操作的次數 m 和取模的基數 MOD
  • 接著將數列存儲在線段樹數組中,并將 n 擴展為 2 的冪次方。
  • 調用 build 函數構建線段樹。
  • 最后循環處理 m 次操作,根據操作類型調用 updatequery 函數。

復雜度分析

  • 時間復雜度:每次更新和查詢操作的時間復雜度均為 O ( log ? n ) O(\log n) O(logn),因此總的時間復雜度為 O ( m log ? n ) O(m \log n) O(mlogn)
  • 空間復雜度:線段樹數組和懶標記數組的空間復雜度均為 O ( 4 n ) O(4n) O(4n),因此總的空間復雜度為 O ( n ) O(n) O(n)

完整代碼:

// P3373 【模板】線段樹 2
#include <iostream>
#include <cmath>
using namespace std;
#define MAXN 400002
#define lson (root*2)
#define rson (root*2+1)int MOD;
long long sgmt[MAXN], lazy_mul[MAXN], lazy_add[MAXN];void push_up(int root) {sgmt[root] = sgmt[lson] + sgmt[rson];sgmt[root] %= MOD;
}void push_down(int root, int len) {if (lazy_mul[root] == 1 && lazy_add == 0) return;lazy_mul[lson] *= lazy_mul[root], lazy_mul[lson] %= MOD;lazy_mul[rson] *= lazy_mul[root], lazy_mul[rson] %= MOD;lazy_add[lson] *= lazy_mul[root], lazy_add[lson] %= MOD;lazy_add[rson] *= lazy_mul[root], lazy_add[rson] %= MOD;lazy_add[lson] += lazy_add[root], lazy_add[lson] %= MOD;lazy_add[rson] += lazy_add[root], lazy_add[rson] %= MOD;sgmt[lson] *= lazy_mul[root], sgmt[lson] %= MOD;sgmt[lson] += (len/2)*lazy_add[root], sgmt[lson] %= MOD;sgmt[rson] *= lazy_mul[root], sgmt[rson] %= MOD;sgmt[rson] += (len/2)*lazy_add[root], sgmt[rson] %= MOD;lazy_mul[root] = 1, lazy_add[root] = 0;
}void update(int a, int b, long long c, long long d, int l, int r, int root) {if (a <= l && r <= b) {sgmt[root] *= c, sgmt[root] %= MOD;sgmt[root] += (r-l+1)*d, sgmt[root] %= MOD;lazy_mul[root] *= c, lazy_mul[root] %= MOD;lazy_add[root] *= c, lazy_add[root] %= MOD;lazy_add[root] += d, lazy_add[root] %= MOD;return;}push_down(root,r-l+1);int mid = (l+r)/2;if (a <= mid) update(a,b,c,d,l,mid,lson);if (b > mid) update(a,b,c,d,mid+1,r,rson);push_up(root);
}long long query(int a, int b, int l, int r, int root) {if (a <= l && r <= b) return sgmt[root];push_down(root,r-l+1);long long ans = 0;int mid = (l+r)/2;if (a <= mid) ans += query(a,b,l,mid,lson), ans %= MOD;if (b > mid) ans += query(a,b,mid+1,r,rson), ans %= MOD;return ans;
}void build(int l, int r, int root) {if (l == r) return;int mid = (l+r)/2;build(l,mid,lson);build(mid+1,r,rson);push_up(root);return;
}int main() {for (int i = 1; i < MAXN; i++)lazy_mul[i] = 1;int n, m; cin >> n >> m >> MOD;int npot = 1 << (int)ceil(log2(n));for (int i = 0; i < n; i++)cin >> sgmt[npot+i];n = npot;int l = 1, r = n, root = 1;build(l,r,root);while (m--) {int op, a, b, c; cin >> op >> a >> b;if (op == 1) {cin >> c; update(a,b,c,0,l,r,root);} else if (op == 2) {cin >> c; update(a,b,1,c,l,r,root);} elsecout << query(a,b,l,r,root)%MOD << endl;}return 0;
}

感謝閱讀在這里插入圖片描述

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

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

相關文章

【計算機視覺】CV實戰項目- COVID 社交距離檢測(covid-social-distancing-detection)

COVID 社交距離檢測&#xff08;covid-social-distancing-detection&#xff09; 一、項目概述二、項目架構三、環境搭建四、運行項目五、輸出結果六、常見問題及解決方法報錯1. cv2.error: OpenCV(4.11.0) :-1: error: (-5:Bad argument) in function circle報錯2 cv2.circle(…

CMake使用教程

一、CMake 簡介 CMake 是一個跨平臺的構建工具&#xff0c;用于自動化生成不同平臺&#xff08;如 Makefile、Visual Studio、Xcode 等&#xff09;的構建文件。它的核心是編寫 CMakeLists.txt 文件&#xff0c;定義項目的構建規則。 二、安裝 CMake Linux: sudo apt-get ins…

大模型Rag - 兩大檢索技術

一、稀疏檢索&#xff1a;關鍵詞匹配的經典代表 稀疏檢索是一種基于關鍵詞統計的傳統檢索方法。其基本思想是&#xff1a;通過詞頻和文檔頻率來衡量一個文檔與查詢的相關性。 核心原理 文檔和查詢都被表示為稀疏向量&#xff08;如詞袋模型&#xff09;&#xff0c;只有在詞…

LNA設計

設計目的 為后級提供足夠的增益以克服后級電路噪聲 盡可能小的噪聲和信號失真 確保輸入和輸出端的阻抗匹配 確保信號線性度 評價標準 噪聲系數 功率增益 工作頻率和帶寬 輸入信號功率動態范圍 端口電壓駐波比 穩定性 基于SP模型的LNA設計 直流分析 S參數分析 設計指標 &#xf…

Vue 常見組件及使用方式全解析

一、引言 在 Vue 開發中&#xff0c;組件是構建復雜用戶界面的基石。通過使用各種常見組件&#xff0c;我們可以快速搭建出功能豐富、交互性強的應用程序。本文將詳細介紹 Vue 開發中一些常見組件及其使用方式。 二、基礎 UI 組件 &#xff08;一&#xff09;按鈕組件&#…

設計測試用例模板

面試時問你一個場景&#xff0c;要你設計測試用例&#xff0c;你會怎么回答&#xff1f; 面試官讓你設計一個功能的測試用例&#xff0c;比如“上傳文件功能”&#xff0c;其實就是想考你&#xff1a; 思維是否全面能不能抓住重點會不會分類和使用測試方法有沒有考慮異常情況…

Git 解決“Filename too long”問題

在 Windows 系統中使用 Git 時&#xff0c;遇到 Filename too long 錯誤通常是由于系統默認的路徑長度限制&#xff08;260 字符&#xff09;導致的。以下是綜合多種場景的解決方案&#xff1a; 一、快速解決方法 啟用 Git 長路徑支持 通過 Git 配置命令允許處理超長文件名&am…

Spring Boot 3 + SpringDoc:打造接口文檔

1、背景公司 新項目使用SpringBoot3.0以上構建&#xff0c;其中需要對外輸出接口文檔。接口文檔一方面給到前端調試&#xff0c;另一方面給到測試使用。 2、SpringDoc 是什么&#xff1f; SpringDoc 是一個基于 Spring Boot 項目的庫&#xff0c;能夠自動根據項目中的配置、…

Swagger2Refit

把swagger相關接口轉成refit格式&#xff0c;以便其他服務調用 使用工具Refitter. Refitter 項目使用教程 Refit Client API Generator for OpenAPI 項目地址: github.com GitCode - 全球開發者的開源社區,開源代碼托管平臺 安裝 Refitter CLI 工具 首先&#xff0c;通過…

【java 13天進階Day05】數據結構,List,Set ,TreeSet集合,Collections工具類

常見的數據結構種類 集合是基于數據結構做出來的&#xff0c;不同的集合底層會采用不同的數據結構。不同的數據結構&#xff0c;功能和作用是不一樣的。數據結構&#xff1a; 數據結構指的是數據以什么方式組織在一起。不同的數據結構&#xff0c;增刪查的性能是不一樣的。不同…

systemctl管理指令

今天我們來繼續學習服務管理指令,接下來才是重頭戲-systemctl,那么話不多說,直接開始吧. systemctl管理指令 1.基本語法: systemctl [start | stop | restart | status]服務 注&#xff1a;systemctl指令管理的服務在/usr/lib/ systemd/system查看 2.systemctl設置服務的自…

STM32單片機教程:從零開始打造智能天氣時鐘

STM32單片機教程&#xff1a;從零開始打造智能天氣時鐘 大家好&#xff01;今天我想為大家詳細介紹一下我們的STM32課程&#xff0c;以及如何從零基礎逐步掌握單片機開發技能&#xff0c;最終實現一個完整的智能天氣時鐘項目。 課程面向人群 本課程主要面向那些已經通過野火…

Neovim插件深度解析:mcphub.nvim如何用MCP協議重構開發體驗

在AI與工具鏈深度融合的今天,Neovim 作為現代開發者的生產力工具,正通過插件生態不斷突破邊界。mcphub.nvim 作為一款基于 MCP(Model Context Protocol) 協議的插件,重新定義了Neovim與智能工具的交互方式。它不僅簡化了MCP服務器的集成與管理,更通過直觀的UI和生態整合,…

第33講|遙感大模型在地學分類中的初探與實戰

目錄 ?? 一、什么是“遙感大模型”? ?? 二、遙感大模型在地學分類中的優勢 ??三、案例:使用 Segment Anything Model (SAM) 進行遙感地物分割 ?? 1. 安裝與依賴配置(PyTorch) ?? 2. 讀取遙感圖像(可用 Sentinel-2 偽彩色圖) ?? 3. SAM 模型載入 ?? …

MATLAB - 小車倒立擺的非線性模型預測控制(NMPC)

系列文章目錄 目錄 系列文章目錄 前言 一、擺錘/小車組件 二、系統方程 三、控制目標 四、控制結構 五、創建非線性 MPC 控制器 六、指定非線性設備模型 七、定義成本和約束 八、驗證非線性 MPC 控制器 九、狀態估計 十、MATLAB 中的閉環仿真 十一、使用 MATLAB 中…

JAVA文件I/O

目錄 一、三種路徑的分類&#xff1a; 1、絕對路徑&#xff1a; 2、相對路徑&#xff1a; 3、基準目錄&#xff1a; 二、文件的種類&#xff1a; 三、利用JAVA操作文件&#xff1a; 1、File類的構造方法&#xff1a; 2、File 類方法的使用&#xff1a; 使用例子&#…

焊接機器人的設計

一、引言 隨著制造業的發展&#xff0c;焊接工藝在各個領域得到廣泛應用。焊接機器人具有焊接質量高、效率高、勞動強度低等優點&#xff0c;能夠滿足現代制造業對焊接生產的要求。設計一款性能優良的焊接機器人&#xff0c;對于提高焊接生產的自動化水平和產品質量具有重要意…

Thymeleaf簡介

在Java中&#xff0c;模板引擎可以幫助生成文本輸出。常見的模板引擎包括FreeMarker、Velocity和Thymeleaf等 Thymeleaf是一個適用于Web和獨立環境的現代服務器端Java模板引擎。 Thymeleaf 和 JSP比較&#xff1a; Thymeleaf目前所作的工作和JSP有相似之處&#xff0c;Thyme…

(論文閱讀)RNNoise 基于遞歸神經網絡的噪聲抑制庫

RNNoise 是一個基于遞歸神經網絡的噪聲抑制庫。 有關該算法的描述見以下論文&#xff1a; J.-M. Valin, A Hybrid DSP/Deep Learning Approach to Real-Time Full-Band Speech Enhancement, Proceedings of IEEE Multimedia Signal Processing (MMSP) Workshop, arXiv:1709.08…

DevOps-文章目錄

01什么是DevOps 02DevOps基礎環境準備 03-DevOps-安裝并初始化Gitlab 04-DevOps-安裝并初始化Jenkins 05-DevOps-Jenkins自動拉取構建代碼1 05-DevOps-Jenkins自動拉取構建代碼2 06-DevOps-自動構建Docker鏡像 07-DevOps-安裝部署Harbor鏡像倉庫 08-DevOps-向Harbor上傳自定義鏡…