樹狀陣列2 更高深的樹狀陣列

2021-08-19 19:59:32 字數 2554 閱讀 9469

一、區間修改區間求和

這個東西可就不是把 單點查詢區間修改 和 單點修改區間查詢 合起來那麼簡單了,仔細想想,拿之前的辦法都不咋地好做,那麼怎麼辦呢,我們還是要用到差分陣列,設原陣列為a,差分陣列為b,則b[1]=a[1],b[i]=a[i]-a[i-1]

那麼區間修改我們就解決了,只需要log的時間即可,但是,這種做法對於區間求和就很弱了。我們首先看一下用它求字首和是什麼樣的(只要知道怎麼求字首和那麼區間求值也就可以用字首和相減得到了):

比如要求a[1]~a[i]:

(b[1])+(b[1]+b[2])+(b[1]+b[2]+b[3])+……+(b[1]+b[2]+……+b[i])

=b[1]*i+b[2]*(i-1)+……+b[i]*1

化簡後我們得到的是這麼個東西,但是顯然的,這種b[1]*i,b[2]*(i-1)我們是無法用樹狀陣列維護的,因為i是時刻在變化的,所以,我們再把這個式子搞一下:

=(b[1]+b[2]+……+b[i])*i-(b[1]*0+b[2]*1+b[3]*2+……+b[i]*(i-1))

然後!我們就發現,這個式子可以維護了!這個式子分成兩部分:

(b[1]+b[2]+……+b[i])*i

這一部分也就是b的乙個字首和乘i,字首和是可以維護的!

(b[1]*0+b[2]*1+b[3]*2+……+b[i]*(i-1))

可以發現,對於每個b[i],都只會乘乙個固定的數——(i-1),所以,也是可以維護的!

那麼,查詢操作就解決了,用兩個樹狀陣列維護即可,那麼修改操作時同時修改這兩個樹狀陣列即可。

**如下:

#include #include int n,m;

int tree[100010],tr[100010];//tree是差分陣列b的樹狀陣列,tr是b[i]*(i-1)的樹狀陣列

int lowbit(int x)

void change(int *a,int x,int y)

int get(int *a,int x)

void ch(int x,int y)//修改

int print(int x)//查詢,也就是(b[1]~b[i])*i - (b[1]*0+b[2]*1+...+b[i]*(i-1))

int main()

for(int i=1;i<=m;i++)

else}}

二、二維樹狀陣列

(1)單點修改區間查詢

其實,二維的樹狀陣列還真就是加多一維而已,其他什麼都沒有變化,但是可能讓人費解,怎麼就只是多一維的事呢?

我們設這個矩陣的樹狀陣列為tree[i][j]

j這一維是用來維護列的,那麼自然地,i這一維就是用來維護行的啦,維護的方法都按樹狀陣列的方法來維護,那麼把他們組合起來之後,tree[i][j]表示的就是——在i節點管理的行中,j節點管理的列的和。

可能不大好理解,那麼我就良心的上個圖吧!

就比如這幅圖,tree[4][6]所管理的範圍就是圖中黃色部分

這樣應該懂了吧qwq

**如下:

#include #include int tree[1010][1010];

int n,m,k;

inline int lowbit(int x)

void add(int x,int y,int z)

int sum(int x,int y)

int main()

scanf("%d",&k);

for(int p=1;p<=k;p++)

else//求(x,y)到(xx,yy)這個矩陣內的點的和}}

(2)區間修改單點查詢

我們設d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1],d就是差分陣列,雖然看起來可能比較奇怪,但是他依然滿足這個性質:差分陣列的字首和表示這個點。所以,每次修改矩陣時,其實就只需要修改d[xx+1][yy+1],d[xx+1][y],d[x][yy+1],d[x][y]四個點即可,求點的話就用維護d值即可,寫一棵改點求段的二維樹狀陣列即可。

**就懶得貼了。

(3)區間修改區間查詢

類似的,依然使用上面的差分陣列,考慮怎麼維護矩陣的字首和(注意是a陣列的字首和)。

因為**:

#include #include int tr1[2100][2100],tr2[2100][2100],tr3[2100][2100],tr4[2100][2100];//tr1~4對應維護上面的d[i][j],j*d[i][j],i*d[i][j],i*j*d[i][j]

int n,m;

int lowbit(int x)

void change(int x,int y,int z)

}}int print(int x,int y)

int main()

else}}

樹狀陣列2

1157 新年彩燈 time limit 1 sec memory limit 128 mb submit 73 solved 25 submit status web board description 新年將至,yy準備掛一片彩燈,形狀呈矩形,已知彩燈剛掛完的彩燈共有n n盞 第一排編號為 1,...

樹狀陣列模板2

如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數數加上x 2.求出某乙個數的和 輸入輸出格式 輸入格式 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含2或4個整數,表示乙個操作...

模板 樹狀陣列 2

題目鏈結 如題,已知乙個數列,你需要進行下面兩種操作 將某區間每乙個數數加上 x 求出某乙個數的值。第一行包含兩個整數 n m,分別表示該數列數字的個數和操作的總個數。第二行包含 n 個用空格分隔的整數,其中第 i 個數字表示數列第 i 項的初始值。接下來 m 行每行包含 2 或 4個整數,表示乙個...