一、區間修改區間求和
這個東西可就不是把 單點查詢區間修改 和 單點修改區間查詢 合起來那麼簡單了,仔細想想,拿之前的辦法都不咋地好做,那麼怎麼辦呢,我們還是要用到差分陣列,設原陣列為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個整數,表示乙個...