樹套樹從入門到去世

luqyou發表於2024-03-20

如何實現資料結構的巢狀?

首先我們知道,單個資料結構是對一些存有某些資訊的節點進行操作,從而達到目的。

然後我們將這些節點換成另一種資料結構,更改的時候對某些資料結構進行修改,就可以實現巢狀。

二維樹狀陣列

其實是最好寫的一種樹套樹。

單點修改,區間查詢

就像上文說的一樣,我們對每一行開一個樹狀陣列,維護該列的資訊,再使用一個樹狀陣列來維護這些樹狀陣列,單點修改時直接在大樹狀陣列裡修改小樹狀陣列即可。

區間查詢做一個差分就好了。

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);
}

相關文章