[python刷題模板] LogTrick

[python刷題模板] LogTrick

    • 一、 算法&數據結構
      • 1. 描述
      • 2. 復雜度分析
      • 3. 常見應用
      • 4. 常用優化
    • 二、 模板代碼
      • 1. 特定或值的最短子數組
      • 2. 找特定值
      • 3. 找位置j的最后一次被誰更新
      • 4. 問某個或和的數量
    • 三、其他
    • 四、更多例題
    • 五、參考鏈接

一、 算法&數據結構

1. 描述

LogTrick可以用來計算子段區間的可重復貢獻問題(即op(x,x) = x, 通常就是指ior、iand、gcd)信息。
通常會關注整個數組的信息,而不僅僅是某一個位置上的答案。
下文描述以或和為例。
# 	模板1
def log_trick_vs(nums: List[int], op=and_):"""獲取nums的所有子段的'與值',返回所有值,共nlogU個。由于不計算個數,不需要計算左右邊界,因此常數低,快1/3左右---注意會直接修改原數組,可酌情拷貝使用-----"""res = set()for i, v in enumerate(nums):res.add(v)  # 在這行做你想做的事for j in range(i - 1, -1, -1):if op(nums[j], v) == nums[j]: breaknums[j] = op(nums[j], v)res.add(nums[j])  # 在這行做你想做的事return res
  • 解釋上述代碼:
  1. 向右遍歷nums到i時,更新前邊訪問過的位置j,在j上儲存的信息為nums[j]=op(j…i),發現這個信息是從i-1層轉移過來的,因此可以遞推。
  2. 當遇到op(nums[j], v) == nums[j]時,即無法使op(j…i)超過op(j…i-1)時,可以退出,繼續向前也無法更新nums[j]了。證明,以或運算為例:
    1. 由于離i越遠,或和越大,可以證明左邊的數字一定大于等于右邊,且一定包含右邊,即nums[i]∈nums[i-1]。
    2. 若nums[i]|v==nums[i],證明nums[i]一定包含了v,那么nums[i-1]肯定也包含了v。即v∈nums[i]∈nums[i-1]。
  3. 同時由于j是從i向左遍歷的,可以發現這樣可以完整無遺漏的遍歷到所有以i為右端點的子段的或和所有可能值的右半部分。而左半部分由于i無法更新到,會有i-1、i-2…或其他更新到。
# 模板2
def log_trick_v_cnt(nums: List[int], op=and_):"""獲取nums的所有子段'與值',返回所有值的個數,共nlogU個。時間復雜度O(nlogU)"""res = defaultdict(int)dp = []  # 順序儲存 [左邊界,右邊界),值for pos, cur in enumerate(nums):for v in dp:v[2] = op(v[2], cur)dp.append([pos, pos + 1, cur])ptr = 0for v in dp[1:]:  # 雙指針向前合并去重if dp[ptr][2] != v[2]:ptr += 1dp[ptr] = velse:dp[ptr][1] = v[1]# dp = dp[: ptr + 1]del dp[ptr + 1:]for l, r, v in dp:res[v] += r - lreturn res
  • 這是另一種寫法,顯式創建了每一層的dp數組,并記錄了左右邊界。
  • 由于每一層只有logU種可能性,且是單調的,用了雙指針的技巧維護擴縮容。

2. 復雜度分析

  1. 時間復雜度整體O(nlog2U);gcd的話再多一個gcd的log。證明:
    分析每個i向前能走多遠比較困難,我們分析Nums[j],每個數字被更新多少次。
    由于每個位置被更新時一定會變大,或這個動作會保證數字變大時,至少會多一個位置的0變成1。因此每個數字至多變大log(U)次
  2. 空間復雜度:如果要存所有子段或和,那共有O(nlogU)個;否則通常可以復用nums原數組,則額外空間只需要O(1)

3. 常見應用

  1. (找值)枚舉所有區間子段的or、and、gcd,找最大、最小、最近值等。
  2. (找段)以每個位置i為右(左)端點,不同子段與的左端點起止位置,以此也可以計算子段數量。

4. 常用優化

  1. 如果只關心值信息本身,那么可以復用nums數組,原地修改,效率極高。
  2. 找段時,可以用字典儲存每個信息對應的段首尾,顯式儲存以當前位置為結尾的或和這個dp數組。
  3. 更新過程中,截止當前位置的左邊數字是單調的,可以二分。

二、 模板代碼

1. 特定或值的最短子數組

例題: 3097. 或值至少為 K 的最短子數組 II

  • 題目要求子段的或值至少為k,直接套模板,當判斷超過k時,i-j+1就可以更新以i為右端點的答案。
class Solution:def minimumSubarrayLength(self, nums: List[int], k: int) -> int:ans = inf for i, v in enumerate(nums):if v >= k:return 1 for j in range(i-1,-1,-1):if (nums[j]|v) >= k:ans = min(ans, i-j+1)if (nums[j]|v) == nums[j]:break nums[j] |= v return ans if ans < inf else -1

2. 找特定值

鏈接: 3171. 找到按位或最接近 K 的子數組

  • 本地直接問所有或值中最接近k的是幾,那么貼模板,把所有值遍歷一次就行
class Solution:def minimumDifference(self, nums: List[int], k: int) -> int:ans = inffor i, x in enumerate(nums):ans = min(ans, abs(x - k))for j in range(i - 1, -1, -1):if nums[j] | x == nums[j]:breaknums[j] |= xans = min(ans, abs(nums[j] - k))return ans

3. 找位置j的最后一次被誰更新

鏈接: 2411. 按位或最大的最小子數組長度

  • 題目問以每個i為左端點,向右達到最大或的位置。
  • 考慮logTrick時間復雜度的證明:每個nums[j]只會被變大logU次
class Solution:def smallestSubarrays(self, nums: List[int]) -> List[int]:n = len(nums) ans = [1]*nfor i, v in enumerate(nums):for j in range(i-1,-1,-1):             if nums[j] | v == nums[j]:break nums[j] |= v ans[j] = i-j+1           return ans

4. 問某個或和的數量

鏈接: [3209. 子數組按位與值為 K 的數目]https://leetcode.cn/problems/number-of-subarrays-with-and-value-of-k/description/)

  • 貼模板2
def log_trick_v_cnt(nums: List[int], op=and_):res = defaultdict(int)dp = []  # 順序儲存 [左邊界,右邊界),值for pos, cur in enumerate(nums):for v in dp:v[2] = op(v[2], cur)dp.append([pos, pos + 1, cur])ptr = 0for v in dp[1:]:  # 雙指針向前合并去重if dp[ptr][2] != v[2]:ptr += 1dp[ptr] = velse:dp[ptr][1] = v[1]# dp = dp[: ptr + 1]del dp[ptr + 1:]  # little fasterfor l, r, v in dp:res[v] += r - lreturn res
class Solution:def countSubarrays(self, nums: List[int], k: int) -> int:res = log_trick_v_cnt(nums)return res[k]

三、其他

  1. 之所以算trick,這個做法其實不太通用,應對的場景比較局限。
  2. 當固定某個端點時,向一側的子段值是單調的,因此以上所有題目都可以用st表+二分解決。如果覺得logTrick不好理解,可以先嘗試本方法解決以上問題。

四、更多例題

  • 2447. 最大公因數等于 K 的子數組數目

五、參考鏈接

  • 鏈接: 靈神的位運算題單

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

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

相關文章

Vim與VS Code

Vim is a clone, with additions, of Bill Joys vi text editor program for Unix. It was written by Bram Moolenaar based on source for a port of the Stevie editor to the Amiga and first released publicly in 1991.其實這個本身不是 IDE &#xff08;只有在加入和配置…

[2025CVPR-圖象分類方向]CATANet:用于輕量級圖像超分辨率的高效內容感知標記聚合

?1. 研究背景與動機? ?問題?&#xff1a;Transformer在圖像超分辨率&#xff08;SR&#xff09;中計算復雜度隨空間分辨率呈二次增長&#xff0c;現有方法&#xff08;如局部窗口、軸向條紋&#xff09;因內容無關性無法有效捕獲長距離依賴。?現有局限?&#xff1a; SPI…

課題學習筆記3——SBERT

1 引言在構建基于知識庫的問答系統時&#xff0c;"語義匹配" 是核心難題 —— 如何讓系統準確識別 "表述不同但含義相同" 的問題&#xff1f;比如用戶問 "對親人的期待是不是欲&#xff1f;"&#xff0c;系統能匹配到知識庫中 "追名逐利是欲…

在Word和WPS文字中把全角數字全部改為半角

大部分情況下我們在Word或WPS文字中使用的數字或標點符號都是半角&#xff0c;但是有時不小心按錯了快捷鍵或者點到了輸入法的全角半角切換圖標&#xff0c;就輸入了全角符號和數字。不用擔心&#xff0c;使用它們自帶的全角、半角轉換功能即可快速全部轉換回來。一、為什么會輸…

數據結構的基本知識

一、集合框架1、什么是集合框架Java集合框架(Java Collection Framework),又被稱為容器(container),是定義在java.util包下的一組接口(interfaces)和其實現類(classes).主要表現為把多個元素(element)放在一個單元中,用于對這些元素進行快速、便捷的存儲&#xff08;store&…

WebStack-Hugo | 一個靜態響應式導航主題

WebStack-Hugo | 一個靜態響應式導航主題 #10 shenweiyan announced in 1.3-折騰 WebStack-Hugo | 一個靜態響應式導航主題#10 ?編輯shenweiyan on Oct 23, 2023 6 comments 7 replies Return to top shenweiyan on Oct 23, 2023 Maintainer Via&#xff1a;我給自己…

01 基于sklearn的機械學習-機械學習的分類、sklearn的安裝、sklearn數據集、數據集的劃分、特征工程中特征提取與無量綱化

文章目錄機械學習機械學習分類1. 監督學習2. 半監督學習3. 無監督學習4. 強化學習機械學習的項目開發步驟scikit-learn1 scikit-learn安裝2 sklearn數據集1. sklearn 玩具數據集鳶尾花數據集糖尿病數據集葡萄酒數據集2. sklearn現實世界數據集20 新聞組數據集3. 數據集的劃分特…

攜全雙工語音通話大模型亮相WAIC,Soul重塑人機互動新范式

近日&#xff0c;WAIC 2025在上海隆重開幕。作為全球人工智能領域的頂級盛會&#xff0c;本屆WAIC展覽聚焦底層能力的演進與具體垂類場景的融合落地。堅持“模應一體”方向、立足“AI社交”的具體場景&#xff0c;Soul App此次攜最新升級的自研端到端全雙工語音通話大模型亮相&…

第2章 cmd命令基礎:常用基礎命令(1)

Hi~ 我是李小咖&#xff0c;主要從事網絡安全技術開發和研究。 本文取自《李小咖網安技術庫》&#xff0c;歡迎一起交流學習&#x1fae1;&#xff1a;https://imbyter.com 本節介紹的命令有目錄操作&#xff08;cd&#xff09;、清屏操作&#xff08;cls&#xff09;、設置顏色…

Java 10 新特性解析

Java 10 新特性解析 文章目錄Java 10 新特性解析1. 引言2. 本地變量類型推斷&#xff08;JEP 286&#xff09;2.1. 概述2.2. 使用場景2.3. 限制2.4. 與之前版本的對比2.5. 風格指南2.6. 示例代碼2.7. 優點與注意事項3. 應用程序類數據共享&#xff08;JEP 310&#xff09;3.1. …

【WRF工具】服務器中安裝編譯GrADS

目錄 安裝編譯 GrADS 所需的依賴庫 conda下載庫包 安裝編譯 GrADS 編譯前檢查依賴可用性 安裝編譯 GrADS 參考 安裝編譯 GrADS 所需的依賴庫 以統一方式在 $HOME/WRFDA_LIBS/grads_deps 下安裝所有依賴: # 選擇一個目錄用于安裝所有依賴庫 export DIR=$HOME/WRFDA_LIBS庫包1…

數據結構之隊列(C語言)

1.隊列的定義&#xff1a; 隊列&#xff08;Queue&#xff09;是一種基礎且重要的線性數據結構&#xff0c;遵循先進先出&#xff08;FIFO&#xff09;?? 原則&#xff0c;即最早入隊的元素最先出隊&#xff0c;與棧不同的是出隊列的順序是固定的。隊列具有以下特點&#xff…

C#開發基礎之深入理解“集合遍歷時不可修改”的異常背后的設計

前言 歡迎關注【dotnet研習社】&#xff0c;今天我們聊聊一個基礎問題“集合已修改&#xff1a;可能無法執行枚舉操作”背后的設計。 在日常 C# 開發中&#xff0c;我們常常會操作集合&#xff08;如 List<T>、Dictionary<K,V> 等&#xff09;。一個新手開發者極…

【工具】圖床完全指南:從選擇到搭建的全方位解決方案

前言 在數字化內容創作的時代&#xff0c;圖片已經成為博客、文檔、社交媒體等平臺不可或缺的元素。然而&#xff0c;如何高效、穩定地存儲和分發圖片資源&#xff0c;一直是內容創作者面臨的重要問題。圖床&#xff08;Image Hosting&#xff09;作為專門的圖片存儲和分發服務…

深度學習篇---PaddleDetection模型選擇

PaddleDetection 是百度飛槳推出的目標檢測開發套件&#xff0c;提供了豐富的模型庫和工具鏈&#xff0c;覆蓋從輕量級移動端到高性能服務器的全場景需求。以下是核心模型分類、適用場景及大小選擇建議&#xff08;通俗易懂版&#xff09;&#xff1a;一、主流模型分類及適用場…

cmseasy靶機密碼爆破通關教程

靶場安裝1.首先我們需要下載一個cms靶場CmsEasy_7.6.3.2_UTF-8_20200422,下載后解壓在phpstudy_pro的網站根目錄下。2.然后我們去訪問一下安裝好的網站&#xff0c;然后注冊和鏈接數據庫3.不知道自己數據庫密碼的可以去小皮面板里面查看4.安裝好后就可以了來到后臺就可以了。練…

【C語言】指針深度剖析(一)

文章目錄一、內存和地址1.1 內存的基本概念1.2 編址的原理二、指針變量和地址2.1 取地址操作符&#xff08;&&#xff09;2.2 指針變量和解引用操作符&#xff08;*&#xff09;2.2.1 指針變量2.2.2 指針類型的解讀2.2.3 解引用操作符2.3 指針變量的大小三、指針變量類型的…

半導體企業選用的跨網文件交換系統到底應該具備什么功能?

在半導體行業的數字化轉型過程中&#xff0c;跨網文件交換已成為連接研發、生產、供應鏈的關鍵紐帶。半導體企業的跨網文件交換不僅涉及設計圖紙、工藝參數等核心知識產權&#xff0c;還需要滿足跨國協同、合規審計等復雜需求。那么&#xff0c;一款適合半導體行業的跨網文件交…

影刀RPA_初級課程_玩轉影刀自動化_網頁操作自動化

聲明&#xff1a;相關內容來自影刀學院&#xff0c;本文章為自用筆記&#xff0c;切勿商用&#xff01;&#xff08;若有侵權&#xff0c;請聯絡刪除&#xff09; 1. 基本概念與操作 1.1 正確處理下拉框元素&#xff08;先判斷頁面元素&#xff0c;后進行流程編制&#xff09;…

Spark初探:揭秘速度優勢與生態融合實踐

更多推薦閱讀 Spark與Flink深度對比&#xff1a;大數據流批一體框架的技術選型指南-CSDN博客 LightProxy使用操作手冊-CSDN博客 Sentry一看就會教程_sentry教程-CSDN博客 微前端架構解析&#xff1a;核心概念與主流方案特性對比_微前端方案對比-CSDN博客 目錄 Spark為何比Hadoo…