使用樹狀數組的前綴和數組更新,查詢K的下界
首要序列總和陣列是一個集合,它累積交錯元素的總和,直到達到特定的索引。這是一種廣泛應用於組合重構以優化時間複雜度的策略。樹狀數組,也被稱為二進位索引樹(BIT),是一種高效地更新元素並在對數時間複雜度內計算前序列總和的資料庫形式。
在本文中,我們將討論如何使用C 中的Fenwick Tree進行現代化改進,以從一個系列求和數組中揭示給定值的較小極限邊界,這個值被稱為K。
文法
語法定義了兩個函數,update和query,以及一個用於Fenwick樹的主函數,Fenwick樹是一種用於高效範圍查詢和更新操作的資料結構。 update函數接受一個索引idx,一個值val,數組的大小n,以及Fenwick樹數組BIT。它透過將val加入索引idx及其所有祖先的節點來更新Fenwick樹。 query函數接受一個索引idx和Fenwick樹數組BIT。它傳回從根節點到索引idx的節點的累積和。主函數宣告數組的大小n,前綴和數組arr,以及初始化為0的Fenwick樹數組BIT。
void update(int idx, int val, int n, int BIT[]) { while (idx <= n) { BIT[idx] += val; idx += (idx & -idx); } } int query(int idx, int BIT[]) { int sum = 0; while (idx > 0) { sum += BIT[idx]; idx -= (idx & -idx); } return sum; } // Driver code int main() { int n; int arr[n+1]; int BIT[n+1] = {0}; return 0; }
演算法
要確定帶有Fenwick樹更新的前綴和數組中K的最小值,請按照以下複雜的步驟進行 -
實例化大小為 n 1 的 Fenwick 樹 (BIT),將所有元素初始化為 0。
使用 update() 函數修改具有給定前綴和陣列的 Fenwick Tree。
在Fenwick樹上執行查詢以確定K的下界。從n的二進位表示中的最高有效位元開始迭代,直到最低有效位元。使用query()函數驗證目前前綴和是否小於或等於K。如果滿足此條件,將當前前綴和從K中減去,並更新索引以移動到下一個位元。如果不滿足條件,則在不更新索引的情況下移動到下一個位元。
遍歷完所有位元後,索引將表示前綴和陣列中 K 的下界。
輸出所得到的索引作為K的下界。
方法
方法1 − 在Fenwick樹上進行二分查找。在這種方法中,我們在Fenwick樹上執行二分查找以找到K的下界。
方法2 - 在Fenwick樹上進行帶有延遲傳播的二分查找。
方法 1
為了解決這個問題,我們首先將左指標和右指標分別設定為1和n(表示前綴和陣列的大小),然後採用二分查找策略來確定對應於小於或等於K的最大前綴和的索引i。然後,根據前綴和[i]的值是否小於或等於K,更新左指標或右指標的位置。
範例
這段程式碼的基本機制是利用了一種叫做 Fenwick Tree(也稱為 Binary Indexed Tree)的資料結構。它的作用是在前綴和數組中確定指定值 'k' 的下界。這是透過使用更新函數建立 Fenwick Tree 來實現的,該函數將前綴和數組中每個元素的值合併到 Fenwick Tree 的相應位置中。
findLowerBound 函數接著採用二分搜尋演算法,透過查詢函數來找出前綴和陣列中「k」的下界。此函數計算直至 Fenwick 樹中目前索引的值的累積和。最終,程式碼最終識別出前綴和陣列中「k」下界的索引,並將結果顯示到控制台。
#include <iostream> using namespace std; void update(int i, int v, int n, int b[]) { while (i <= n) { b[i] += v; i += (i & -i); } } int query(int i, int b[]) { int s = 0; while (i > 0) { s += b[i]; i -= (i & -i); } return s; } int findLowerBound(int k, int n, int p[], int b[]) { int l = 1, r = n, idx = 0; while (l <= r) { int m = (l + r) / 2; int msum = query(m, b); if (msum <= k) { idx = m; l = m + 1; } else { r = m - 1; } } return idx; } int main() { int n = 5; int p[] = {0, 1, 3, 6, 10, 15}; int b[n + 1] = {0}; for (int i = 1; i <= n; i++) { update(i, p[i], n, b); } int k = 10, idx; idx = findLowerBound(k, n, p, b); cout << "The lower bound of " << k << " is at index " << idx << " in the prefix sum array." << endl; return 0; }
輸出
The lower bound of 10 is at index 3 in the prefix sum array.
方法2
為了進一步優化 Fenwick 樹,可以採用一種稱為惰性傳播的技術。這種方法需要將對 Fenwick Tree 的更新推遲到實際需要時,從而減少更新次數並提高查詢過程的效率。
範例
程式碼提供了一種解決方案,用於在前綴和陣列中定位給定值K的下限。前綴和數組是一個數組,其中每個元素都是原始數組中從索引0到該索引的元素的總和。下限是前綴和陣列中第一個使得到該索引的元素總和等於或超過K的索引。此解決方案使用Fenwick樹資料結構和延遲傳播技術來增強解決方案的效率。程式碼包括修改Fenwick樹、計算前綴和和找出下限的函數。程式碼還初始化了前綴和數組、Fenwick樹和延遲傳播數組。最後,它輸出了前綴和數組中K的下限。
#include <iostream> #include <cstring> using namespace std; void update(int idx, int val, int n, int ft[], int lz[]) { while (idx <= n) ft[idx] += val, idx += (idx & -idx); } int getPrefixSum(int idx, int ft[]) { int sum = 0; while (idx > 0) sum += ft[idx], idx -= (idx & -idx); return sum; } int findLowerBound(int K, int n, int ps[], int ft[], int lz[]) { int l = 1, r = n, lb = 0; while (l <= r) { int m = (l + r) / 2, s = getPrefixSum(m, ft) + lz[m]; if (s <= K) lb = m, l = m + 1; else r = m - 1; } return lb; } int main() { int n = 5; int ps[] = {0, 1, 3, 6, 10, 15}; int ft[n + 1], lz[n + 1]; memset(ft, 0, sizeof(ft)); memset(lz, 0, sizeof(lz)); for (int i = 1; i <= n; i++) update(i, ps[i] - ps[i - 1], n, ft, lz); int K = 10; int lb = findLowerBound(K, n, ps, ft, lz); cout << "For the given array with size " << n << " and prefix sum array ["; for (int i = 1; i <= n; i++) { cout << ps[i]; if (i < n) cout << ", "; } cout << "], the lower bound of " << K << " is at index " << lb << " in the prefix sum array." << endl; return 0; }
輸出
For the given array with size 5 and prefix sum array [1, 3, 6, 10, 15], the lower bound of 10 is at index 4 in the prefix sum array.
結論
關於從精心設計的前綴和數組中挖掘難以捉摸的 K 值閾值的討論,並透過更新進行強化,利用 C 程式設計領域中巧妙的芬威克樹演算法。深入研究兩種高效方法的複雜性:Fenwick 樹上的二分搜尋和帶有惰性傳播的 Fenwick 樹上的二分搜尋。根據您的特定難題的特定要求和限制,仔細選擇最合適的方法。希望這能夠闡明這一難以捉摸的任務的概念化和實現,即利用 C 領域中 Fenwick 樹無與倫比的功能,從帶有更新的前綴和數組中找到 K 的下界。
以上是使用樹狀數組的前綴和數組更新,查詢K的下界的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

C語言數據結構:樹和圖的數據表示與操作樹是一個層次結構的數據結構由節點組成,每個節點包含一個數據元素和指向其子節點的指針二叉樹是一種特殊類型的樹,其中每個節點最多有兩個子節點數據表示structTreeNode{intdata;structTreeNode*left;structTreeNode*right;};操作創建樹遍歷樹(先序、中序、後序)搜索樹插入節點刪除節點圖是一個集合的數據結構,其中的元素是頂點,它們通過邊連接在一起邊可以是帶權或無權的數據表示鄰

文件操作難題的真相:文件打開失敗:權限不足、路徑錯誤、文件被佔用。數據寫入失敗:緩衝區已滿、文件不可寫、磁盤空間不足。其他常見問題:文件遍歷緩慢、文本文件編碼不正確、二進製文件讀取錯誤。

C語言函數是代碼模塊化和程序搭建的基礎。它們由聲明(函數頭)和定義(函數體)組成。 C語言默認使用值傳遞參數,但也可使用地址傳遞修改外部變量。函數可以有返回值或無返回值,返回值類型必須與聲明一致。函數命名應清晰易懂,使用駝峰或下劃線命名法。遵循單一職責原則,保持函數簡潔性,以提高可維護性和可讀性。

C語言函數名定義包括:返回值類型、函數名、參數列表和函數體。函數名應清晰、簡潔、統一風格,避免與關鍵字衝突。函數名具有作用域,可在聲明後使用。函數指針允許將函數作為參數傳遞或賦值。常見錯誤包括命名衝突、參數類型不匹配和未聲明的函數。性能優化重點在函數設計和實現上,而清晰、易讀的代碼至關重要。

C35 的計算本質上是組合數學,代表從 5 個元素中選擇 3 個的組合數,其計算公式為 C53 = 5! / (3! * 2!),可通過循環避免直接計算階乘以提高效率和避免溢出。另外,理解組合的本質和掌握高效的計算方法對於解決概率統計、密碼學、算法設計等領域的許多問題至關重要。

C語言函數是可重複利用的代碼塊,它接收輸入,執行操作,返回結果,可將代碼模塊化提高可複用性,降低複雜度。函數內部機制包含參數傳遞、函數執行、返回值,整個過程涉及優化如函數內聯。編寫好的函數遵循單一職責原則、參數數量少、命名規範、錯誤處理。指針與函數結合能實現更強大的功能,如修改外部變量值。函數指針將函數作為參數傳遞或存儲地址,用於實現動態調用函數。理解函數特性和技巧是編寫高效、可維護、易理解的C語言程序的關鍵。

算法是解決問題的指令集,其執行速度和內存佔用各不相同。編程中,許多算法都基於數據搜索和排序。本文將介紹幾種數據檢索和排序算法。線性搜索假設有一個數組[20,500,10,5,100,1,50],需要查找數字50。線性搜索算法會逐個檢查數組中的每個元素,直到找到目標值或遍歷完整個數組。算法流程圖如下:線性搜索的偽代碼如下:檢查每個元素:如果找到目標值:返回true返回falseC語言實現:#include#includeintmain(void){i

C語言多線程編程指南:創建線程:使用pthread_create()函數,指定線程ID、屬性和線程函數。線程同步:通過互斥鎖、信號量和條件變量防止數據競爭。實戰案例:使用多線程計算斐波那契數,將任務分配給多個線程並同步結果。疑難解答:解決程序崩潰、線程停止響應和性能瓶頸等問題。
