如何實現資料結構的巢狀?
首先我們知道,單個資料結構是對一些存有某些資訊的節點進行操作,從而達到目的。
然後我們將這些節點換成另一種資料結構,更改的時候對某些資料結構進行修改,就可以實現巢狀。
二維樹狀陣列
其實是最好寫的一種樹套樹。
單點修改,區間查詢
就像上文說的一樣,我們對每一行開一個樹狀陣列,維護該列的資訊,再使用一個樹狀陣列來維護這些樹狀陣列,單點修改時直接在大樹狀陣列裡修改小樹狀陣列即可。
區間查詢做一個差分就好了。
int lb(int x){
return x&(-x);
}
void update(int x,int y,int k){
for(int i=x;i<=n;i+=lb(i)){
for(int j=y;j<=m;j+=lb(j)){
c[i][j]+=k;
}
}
}
int query(int x,int y){
int res=0;
for(int i=x;i;i-=lb(i)){
for(int j=y;j;j-=lb(j)){
res+=c[i][j];
}
}
return res;
}
void work(int x,int y,int x_,int y_,int k){
update(x,y,k),update(x,y_+1,-k),update(x_+1,y,-k),update(x_+1,y_+1,k);
}
int getans(int x,int y,int x_,int y_){
return query(x_,y_)-query(x_,y-1)-query(x-1,y_)+query(x-1,y-1);
}
區間修改,單點查詢
想一下我們利用樹狀陣列維護一維序列時的區間修改,單點查詢時怎麼做?
直接維護原序列的差分序列,然後就可以轉換為單點修改,區間查詢了。
二維資訊也是如此。注意容斥即可。
int lb(int x){
return x&(-x);
}
void update(int x,int y,int k){
for(int i=x;i<=n;i+=lb(i)){
for(int j=y;j<=m;j+=lb(j)){
c[i][j]+=k;
}
}
}
int query(int x,int y){
int res=0;
for(int i=x;i;i-=lb(i)){
for(int j=y;j;j-=lb(j)){
res+=c[i][j];
}
}
return res;
}
void work(int x,int y,int x_,int y_,int k){
update(x,y,k),update(x,y_+1,-k),update(x_+1,y,-k),update(x_+1,y_+1,k);
}
int getans(int x,int y,int x_,int y_){
return query(x_,y_)-query(x_,y-1)-query(x-1,y_)+query(x-1,y-1);
}