單點修改,區間查詢 一,二維

2021-10-08 13:23:13 字數 2057 閱讀 6831

不難想到,用乙個陣列來模擬

就比如,單點修改就是這(時間複雜度為o(1));

a[x]

+= k;

求區間內的和

for

(int i = l -

1; i <= r; i++

) sum +

= a[i]

;

這樣的時間複雜度為o(n),如果查詢次數足夠多,就會超時

解決方法一:字首和

這樣在輸入時預處理,查詢只要o(1)時間。但是仔細想想,這樣的話,修改就需要o(n)的時間複雜度了。所以行不通。

解決方法二:樹狀陣列

什麼是樹狀陣列

這樣修改查詢都只需要o(log(n))的時間,大大優化了時間複雜度

例題:題目tp門

題目描述

如題,已知乙個數列,你需要進行下面兩種操作:

1.將某乙個數加上x

2.求出某區間每乙個數的和

輸入格式:

第一行包含兩個整數n、m,分別表示該數列數字的個數和操作的總個數。

第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。

接下來m行每行包含3個整數,表示乙個操作,具體如下:

操作1: 格式:1 x k 含義:將第x個數加上k

操作2: 格式:2 x y 含義:輸出區間[x,y]內每個數的和

樣例樣例輸入

321

2312

0213

樣例輸出

6
正解

這道題很簡單,就直接上**

#include

#define ll long long

const

int maxn =

1e6+5;

ll a[maxn]

, pre[maxn]

, bit[maxn]

;ll n, q;

ll lowbit

(ll x)

void

update

(ll x, ll k)

ll sum

(ll l, ll r)

void

read()

}void

write()

}int

main()

(注:這道題資料範圍比較大,要開long long)

例題:題目tp門

題目描述

給出乙個n*m的零矩陣a,你需要完成如下操作:

x y k:表示元素a[x][y]自增k ;

a b c d:表示詢問左下角為 ,右上角為 的子矩陣內所有數的和。

輸入格式

輸入的第一行有兩個正整數n, m ;

接下來若干行,每行乙個操作,直到檔案結束。

輸出格式

對於每個 2 操作,輸出乙個整數,表示對於這個操作的回答。

分析在一維後面多開乙個陣列就行了

pr[l]

[r]- pr[i -1]

[r]- pr[l]

[j -1]

+ pr[i -1]

[j -1]

;

這就是二維字首和

結合上面的式子,正解就出來了

#include

#define ll long long

const

int maxn =

4200

;ll bit[maxn]

[maxn]

;ll n, m, p;

void

read()

ll lowbit

(ll x)

void

update

(ll x, ll y, ll k)

ll sum

(ll x, ll y, ll l, ll r)

void

write()

}}intmain()

二維樹狀陣列 單點修改,區間查詢(模板)

給你乙個n m的鄰接矩陣,完成以下兩個操作。1 x y k 表示元素 ax,y 自增 k 2 a b c d 表示詢問左上角為 a,b 右下角為 c,d 的子矩陣內所有數的和。input 輸入的第一行有兩個正整數 n,m 接下來若干行,每行乙個操作,直到檔案結束。output 對於每個 2 操作,輸...

樹狀陣列 單點修改區間查詢

樹狀陣列,時間複雜度o mlogn 明顯優於暴力列舉以及字首和,主要用於單點修改區間查詢 當然還有區間修改單點查詢 如果一道題中只有區間查詢,那麼建議使用字首和維護 思想直接理解不好理解,借助資料 a陣列下標12 3456 78數值2 5632 714以上是我們要儲存的a陣列,就是原資料 b陣列下標...

樹狀陣列(單點修改區間查詢)

lowbit是用來取出二進位制中最低位數的1所代表的二進位制的值。只需要記下 就行了 int lowbit int x 將乙個樹的最子節點修改,則其父節點也需要更改,父父節點也需要修改。x x lowbit x 就是用來取出其父節點的。void add int x,int k 能查詢原陣列的字首和,...