數據結構:樹狀數組

老規矩,推薦一篇原理講解清晰的博客!(樹狀數組(詳細分析+應用),看不懂打死我!_樹形數組_鮮果維他命的博客-CSDN博客

相對于線段樹,樹狀數組的優點就是代碼簡潔,容易修改。單缺點就是優點問題只有線段樹才能解決,樹狀數組有一定的局限性。

1,模板

(1)單點修改,區間查詢

int lowbit(int x) {return x & (-x);
}
int add_dandian(int pos, int k)
{for (int i = pos; i <= n; i += lowbit(i)) c[i] += k;
}
int search(int L, int R)
{//利用前綴和相減的性質,[L, R] = [1, R] ?[1, L ? 1]int ans = 0;for (int i = L - 1; i; i -= lowbit(i)) ans -= c[i];for (int i = R; i; i -= lowbit(i)) ans += c[i];return 0;
}

(2)區間修改,單點查詢

我們需要構造出原數組的差分數組b,然后用樹狀數組維護b數組即可

對于區間修改的話,我們只需要對差分數組進行操作即可,例如對區間[L,R]+k,那么我們只需要更

新差分數組add(L,k),add(R+1,-k),這是差分數組的性質.

int lowbit(int x) {return x & (-x);
}
void update(int pos, int k)//pos表示修改點的位置,K表示修改的值也即+K操作
{for (int i = pos; i <= n; i += lowbit(i)) c[i] += k;
}void range_add(int L, int R, int k){update(L, k);update(R + 1, -k);
}int ask(int pos)//返回區間pos到1的總和
{int ans = 0;for (int i = pos; i; i -= lowbit(i)) ans += c[i];return ans;
}

(3)區間修改,區間查詢

void add(ll p, ll x){for(int i = p; i <= n; i += i & -i)sum1[i] += x, sum2[i] += x * p;
}
void range_add(ll l, ll r, ll x){add(l, x), add(r + 1, -x);
}
ll ask(ll p){ll res = 0;for(int i = p; i; i -= i & -i)res += (p + 1) * sum1[i] - sum2[i];return res;
}
ll range_ask(ll l, ll r){return ask(r) - ask(l - 1);
}

2,題目練習

(1)【模板】樹狀數組 1 - 洛谷

?AC代碼

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5;
int n,m,a[N];int lowbit(int x)
{return x&(-x);
}
void add(int pos,int k);
int search(int l,int r);signed main()
{cin>>n>>m;for(int i=1;i<=n;i++){//cin>>a[i];int x;cin>>x;add(i,x);}for(int i=0;i<m;i++){int flag,l,r;cin>>flag>>l>>r;if(flag==1) add(l,r);else cout<<search(l,r)<<endl;}return 0;
}void add(int pos,int k)
{for(int i=pos;i<=n;i+=lowbit(i)){a[i]+=k;}
}int search(int l,int r)
{int sum=0;for(int i=r;i;i-=lowbit(i)){sum+=a[i];}for(int i=l-1;i;i-=lowbit(i)){sum-=a[i];}return sum;
} 

(2)【模板】樹狀數組 2 - 洛谷

?? AC代碼

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5;
int n,m,a[N],b[N];int lowbit(int x)
{return x&(-x);
}
void add(int pos,int k);
int find(int pos);signed main()
{cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];add(i,a[i]-a[i-1]);//差分 }for(int i=0;i<m;i++){int flag,l,r,k;cin>>flag;if(flag==1){cin>>l>>r>>k;add(l,k);add(r+1,-k);}else{cin>>l;cout<<find(l)<<endl;}}return 0;
}void add(int pos,int k)
{for(int i=pos;i<=n;i+=lowbit(i)) b[i]+=k;return;
}int find(int pos)
{int sum=0;for(int i=pos;i;i-=lowbit(i)) sum+=b[i];return sum;
}

(3)逆序隊? 逆序對 - 洛谷

AC代碼

#include <bits/stdc++.h>
using namespace std;
int n, a[5000001], b[5000001];
long long ans;
inline void msort(int l, int r)//歸并排序
{int mid = (l + r) / 2;//取中間 if(l == r)//若l == r了,就代表這個子序列就只剩1個元素了,需要返回 {return;}else{msort(l, mid);//分成l和中間一段,中間 + 1和r一段(二分) msort(mid + 1, r);}int i = l;//i從l開始,到mid,因為現在排序的是l ~ r的區間且要二分合并 int j = mid + 1;//j從mid + 1開始,到r原因同上int t = l;//數組b的下標,數組b存的是l ~ r區間排完序的值 while(i <= mid && j <= r)//同上i,j的解釋 {if(a[i] > a[j])//如果前面的元素比后面大(l ~ mid中的元素 > mid + 1 ~ r中的元素)(逆序對出現!!!) { ans += mid - i + 1;//由于l ~ mid和mid + 1 ~ r都是有序序列所以一旦l ~ mid中的元素 > mid + 1 ~ r中的元素而又因為第i個元素 < i + 1 ~ mid那么i + 1 ~ mid的元素都 > 第j個元素。所以+的元素個數就是i ~ mid的元素個數,及mid - i + 1(歸并排序里沒有這句話,求逆序對里有) b[t++] = a[j++];//第j個元素比i ~ mid的元素都小,那么第j個元素是目前最小的了,就放進b數組里 //++j;//下一個元素(mid + 1 ~ r的元素小,所以加第j個元素) }else{b[t++] = a[i++];//i小,存a[i] //++i;//同理 }}while(i <= mid)//把剩的元素(因為較大所以在上面沒選) {b[t++] = a[i++];//存進去 //++i; }while(j <= r)//同理 {b[t++] = a[j++];//++j;}for(int i = l; i <= r; ++i)//把有序序列b賦值到a里 {a[i] = b[i];}return;
}
int main()
{scanf("%d", &n);for(int i = 1; i <= n; ++i){scanf("%d", &a[i]);}msort(1, n);//一開始序列是1 ~ n printf("%lld", ans);return 0;
}

(4)康托展開? 【模板】康托展開 - 洛谷

AC代碼

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
const int mod = 998244353;
int a[N], w[N]={1,1},tr[N], n,ans;int lowbit(int x) {return x & (-x);
}
void update(int pos, int k) {for (int i = pos; i <= n; i += lowbit(i)) tr[i] += k;return;
}
int query(int pos)
{int sum = 0;for (int i = pos; i; i -= lowbit(i)) sum+=tr[i];return sum;
}signed main()
{cin >> n;for (int i = 1; i <= n; i++) {//求階乘w[i] = (i * w[i - 1]) % mod;update(i, 1);}for (int i = 1; i <= n; i++) {cin >> a[i];ans = (ans + ((query(a[i]) - 1) * w[n-i]) % mod) % mod;update(a[i], -1);//減1后就變成0了}cout << ans+1 << endl;return 0;
}

(5)二維樹狀數組? 上帝造題的七分鐘 - 洛谷

思想:和二維前綴和的思路很相似

AC代碼

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
const int N = 3000;
int board[N][N];
int n, m;// 定義樹狀數組結構(樹狀數組三件套)
struct BIT
{int tr[N][N];  // 樹狀數組int lowbit(int x) {return x & (-x);  // 返回 x 的最低位的 1 所在位置}// 在坐標 (x, y) 處添加值 kvoid add(int x, int y, int k){for (int i = x; i <= n; i += lowbit(i)) {for (int j = y; j <= m; j += lowbit(j)) {tr[i][j] += k;  // 在 (i, j) 處加上值 k}}}// 查詢坐標 (x, y) 處的前綴和int query(int x, int y){int sum = 0;for (int i = x; i; i -= lowbit(i)) {for (int j = y; j; j -= lowbit(j)) {sum += tr[i][j];  // 查詢 (1, 1) 到 (x, y) 的前綴和}}return sum;}
} A, Ai, Aj, Aij;  // 定義四個不同的樹狀數組void Add(int x, int y, int k);
int Ans(int x, int y);int main()
{char ch;cin >> ch >> n >> m;  // 讀取矩陣大小while (cin >> ch) {int x1, x2, y1, y2;cin >> x1 >> y1 >> x2 >> y2;if (ch == 'L') {int num;cin >> num;Add(x1, y1, num);  // 在指定區域添加值 numAdd(x1, y2 + 1, -num);Add(x2 + 1, y1, -num);Add(x2 + 1, y2 + 1, num);}else {cout << Ans(x2, y2) - Ans(x1 - 1, y2) - Ans(x2, y1 - 1) + Ans(x1 - 1, y1 - 1) << endl;// 查詢并輸出給定矩形區域的和}}return 0;
}// 計算 (x, y) 處的結果
int Ans(int x, int y)
{return A.query(x, y) * (x * y + x + y + 1) - Ai.query(x, y) * (y + 1) - Aj.query(x, y) * (x + 1) + Aij.query(x, y);
}// 在坐標 (x, y) 處添加值 num
void Add(int x, int y, int num)
{A.add(x, y, num);Ai.add(x, y, num * x);Aj.add(x, y, num * y);Aij.add(x, y, num * x * y);
}

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

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

相關文章

計算機視覺中的特征檢測和描述

一、說明 這篇文章是關于計算機視覺中特征檢測和描述概念的簡要理解。在其中&#xff0c;我們探討了它們的定義、常用技術、簡單的 python 實現和一些限制。 二、什么是特征檢測和描述&#xff1f; 特征檢測和描述是計算機視覺中的基本概念&#xff0c;在圖像識別、對象跟蹤和圖…

Beats:使用 Filebeat 將 golang 應用程序記錄到 Elasticsearch - 8.x

毫無疑問&#xff0c;日志記錄是任何應用程序最重要的方面之一。 當事情出錯時&#xff08;而且確實會出錯&#xff09;&#xff0c;我們需要知道發生了什么。 為了實現這一目標&#xff0c;我們可以設置 Filebeat 從我們的 golang 應用程序收集日志&#xff0c;然后將它們發送…

Maven教程_編程入門自學教程_菜鳥教程-免費教程分享

教程簡介 Maven 是一款基于 Java 平臺的項目管理和整合工具&#xff0c;它將項目的開發和管理過程抽象成一個項目對象模型&#xff08;POM&#xff09;。開發人員只需要做一些簡單的配置&#xff0c;Maven 就可以自動完成項目的編譯、測試、打包、發布以及部署等工作。Maven 是…

微信小程序備案流程

微信小程序備案流程 &#x1f4d4; 千尋簡筆記介紹 千尋簡筆記已開源&#xff0c;Gitee與GitHub搜索chihiro-notes&#xff0c;包含筆記源文件.md&#xff0c;以及PDF版本方便閱讀&#xff0c;且是用了精美主題&#xff0c;閱讀體驗更佳&#xff0c;如果文章對你有幫助請幫我…

二、異常日志

二、異常日志 &#xff08;一&#xff09;、錯誤碼 錯誤碼的制定原則&#xff1a;快速溯源、溝通標準化錯誤碼不體現版本號和錯誤等級信息全部正常&#xff0c;但不得不填充錯誤碼時返回五個零&#xff1a;00000錯誤碼為字符串類型&#xff0c;共 5 位&#xff0c;分成兩個部分…

win10 anaconda pytorch avalanche-lib 實驗步驟記錄

conda create --name test_python3.10 conda activate test_python3.10 配置conda國內源(北外) conda install pytorch torchvision torchaudio cpuonly -c pytorch pip3 install avalanche-lib -i https://pypi.tuna.tsinghua.edu.cn/simple conda install jupyter jupyte…

[tidb] tiup升級tidb的版本到 v7.1.1

備份 為了避免數據丟失&#xff0c;升級前需要備份當前tidb集群的數據&#xff0c;參考 TiDB 備份與恢復概述 | PingCAP 文檔中心 說明 由于新版本的tidb的tiflash需要cpui支持avx2&#xff0c;所有升級前先驗證當前升級的服務器是否支持avx2。升級的文檔可以參考 使用 TiUP…

Android布局【TableLayout】

文章目錄 說明常見屬性子控件設置屬性 項目結構主要代碼 說明 TableLayout也稱為表格布局 常見屬性 android:collapseColumns&#xff1a;設置需要被隱藏的列的序列號&#xff0c;從0開始android:stretchColumns&#xff1a;設置允許被拉伸的列的列序號&#xff0c;從0開始&…

docker私有鏡像倉庫搭建

1、下載registry鏡像 docker pull registry:2.52、生成登錄私有倉庫的用戶名以及密碼 mkdir -p /opt/registry/auth/ docker run --entrypoint htpasswd registry:2.5 -Bbn username userpwd >> /opt/registry/auth/htpasswd3、創建配置文件 mkdir -p /opt/registry/…

Git - 配置代理 和 取消代理配置

一. 配置代理 (使git走網路代理) git config --global http.proxy socks5://127.0.0.1:1080 git config --global https.proxy socks5://127.0.0.1:1080 其中 1080 是 SOCKS 代理的端口&#xff0c;一般默認 1080&#xff0c;可以在代理工具的設置中查看 地址記錄&#xff1a…

Python中使用隧道爬蟲ip提升數據爬取效率

作為專業爬蟲程序員&#xff0c;我們經常面臨需要爬取大量數據的任務。然而&#xff0c;有些網站可能會對頻繁的請求進行限制&#xff0c;這就需要我們使用隧道爬蟲ip來繞過這些限制&#xff0c;提高數據爬取效率。本文將分享如何在Python中使用隧道爬蟲ip實現API請求與響應的技…

(十八)大數據實戰——Hive的metastore元數據服務安裝

前言 Hive的metastore服務作用是為Hive CLI或者Hiveserver2提供元數據訪問接口。Hive的metastore 是Hive元數據的存儲和管理組件&#xff0c;它負責管理 Hive 表、分區、列等元數據信息。元數據是描述數據的數據&#xff0c;它包含了關于表結構、存儲位置、數據類型等信息。本…

Android Jetpack Compose 中的分頁與緩存展示

Android Jetpack Compose 中的分頁與緩存展示 在幾乎任何類型的移動項目中&#xff0c;移動開發人員在某個時候都會處理分頁數據。如果數據列表太大&#xff0c;無法一次從服務器檢索完畢&#xff0c;這就是必需的。因此&#xff0c;我們的后端同事為我們提供了一個端點&#…

ArcGIS Pro應用—暨基礎入門、制圖、空間分析、影像分析、三維建模、空間統計分析與建模、python融合、案例應用全流程科研能力提升教程

詳情點擊鏈接&#xff1a;ArcGIS Pro應用—暨基礎入門、制圖、空間分析、影像分析、三維建模、空間統計分析與建模、python融合、案例應用全流程科研能力提升教程 第一&#xff1a;GIS及ArcGIS Pro 1.GIS基本原理及常用軟件 2.ArcGIS Pro 安裝與配置 3.ArcGIS Pro 3.0 的新…

C語言自動抓取淘寶商品詳情網頁數據,實現輕松高效爬蟲

你是否曾經遇到過需要大量獲取網頁上的數據&#xff0c;但手動復制粘貼又太過費時費力&#xff1f;那么這篇文章就是為你而寫。今天我們將會詳細討論如何使用C語言實現自動抓取網頁上的數據。本文將會從以下8個方面進行逐步分析討論。 1. HTTP協議的基本原理 在開始之前&…

小白到運維工程師自學之路 第七十三集 (kubernetes應用部署)

一、安裝部署 1、以Deployment YAML方式創建Nginx服務 這個yaml文件在網上可以下載 cat nginx-deployment.yaml apiVersion: apps/v1 #apiVersion是當前配置格式的版本 kind: Deployment #kind是要創建的資源類型&#xff0c;這里是Deploymnet metadata: #metadata是該資源…

Photoshop多圖片與多窗口下排列操作方法

首先&#xff0c;在Photoshop中打開6張圖片&#xff0c;在“窗口”菜單下切換窗口排列狀態&#xff1a; 在 “窗口”菜單下對窗口進行排列&#xff0c;分別呈現如下&#xff1a; &#xff08;一&#xff09;. 點擊“窗口” -> “排列”->"全部垂直拼貼": &am…

本地oracle登錄賬號鎖定處理,the account is locked

1.打開cmd命令窗口 2.打開sqlplus: sqlplus /nolog(加/nolog是不登錄服務器的意思&#xff0c;不加就需要輸賬號密碼) 3.切換到管理員&#xff1a;conn / as sysdba; 第2步第3步可以合并&#xff0c;直接使用sysdba登錄&#xff1a;sqlplus / as sysdba; 4.解鎖賬號&#x…

大端和小端

大端和小端 大端&#xff08;Big Endian&#xff09;和小端&#xff08;Little Endian&#xff09;是兩種不同的字節序排列方式&#xff0c;用于解釋多字節數據在內存中的存儲順序。 在大端字節序中&#xff0c;高位字節&#xff08;最高有效位&#xff09;存儲在低位地址&am…

1. 兩數之和

題目&#xff1a; 給定一個整數數組 nums 和一個整數目標值 target&#xff0c;請你在該數組中找出 和為目標值 target 的那 兩個 整數&#xff0c;并返回它們的數組下標。 你可以假設每種輸入只會對應一個答案。但是&#xff0c;數組中同一個元素在答案里不能重復出現。 你…