HDU 4819 Mosaic 二維線段樹

2021-09-23 07:58:03 字數 2683 閱讀 2229

給定乙個n*n的矩陣,每個格仔都有乙個數,再給出q個詢問,每次詢問以(x,y)為中心的邊長為l的正方形矩陣中的最大值和最小值,並修改(x,y)的值為(max+min)/2

1)四叉樹

對於查詢矩陣的最值+修改問題,考慮二維線段樹,參照一維線段樹的寫法:每次將區間二分成兩個子區間,對應矩陣應對x,y同時二分,也就是4個子矩陣,即左上、右上、左下,右下四部分,所以要建一顆四叉樹,如果當前矩陣為一維時,只需二分成兩個子區間,如下圖所示:

歸納總結得出節點x的兒子節點為:x*4-2+a(0=<a<=3,根節點為1),其他就和一維線段樹一樣了

#include using namespace std;

const int maxn = 1e3+13;

int n,m,x,y,l,t,q,a[maxn][maxn];

struct treetr[maxn*maxn*4];

inline int son(int p,int x)

void pushup1(int x)

}void pushup2(int x)

void build(int x1,int y1,int x2,int y2,int index)

int midx = (x1+x2) >> 1;

int midy = (y1+y2) >> 1;

if(x1 == x2)

else if(y1 == y2)

else

}int a,b;

void query(int x1,int y1,int x2,int y2,int x)

if(tr[x].x1 == tr[x].x2 || tr[x].y1 == tr[x].y2)

else

}void updata(int x1,int y1,int x2,int y2,int x,int val)

if(tr[x].x1 == tr[x].x2 || tr[x].y1 == tr[x].y2)

else

}int main()

}return 0;

}

2)樹套樹先對x軸建一顆一維線段樹,再在其每個節點下建一顆y軸的一維線段樹,那麼x樹的每個節點維護:x軸上[xl,xr],整個y軸的矩陣的資訊,考慮如何向上維護資訊(下圖以縱為x)

(1)如果當前x節點為x樹上的葉子節點,如x2 和 x3,那麼它的y樹就和普通的一維線段樹一樣維護

(2)如果當前x節點不是x樹上的葉子節點,如x1,那麼其y樹的葉子節點是由它的兒子節點的y樹的葉子節點合併而來

int max[maxn<<2][maxn<<2],min[maxn<<2][maxn<<2];  //第一維表示x樹上節點的編號

int t,n,q,a[maxn][maxn],xl,yl,xr,yr,x,y,l,newv,maxv,minv;

inline void pushupx(int x,int y)

inline void pushupy(int x,int y)

void buildy(int l,int r,int y,int x,int k)

int mid = (l+r) >> 1;

buildy(l,mid,y<<1,x,k);

buildy(mid+1,r,y<<1|1,x,k);

pushupy(x,y);

}void buildx(int l,int r,int x)

int mid = (l+r) >> 1;

buildx(l,mid,x<<1);

buildx(mid+1,r,x<<1|1);

buildy(1,n,1,x,0);

}void updatay(int l,int r,int y,int x,int k)

int mid = (l+r) >> 1;

updatay(l,mid,y<<1,x,k);

updatay(mid+1,r,y<<1|1,x,k);

pushupy(x,y);

}void updatax(int l,int r,int x)

int mid = (l+r) >> 1;

updatax(l,mid,x<<1);

updatax(mid+1,r,x<<1|1);

updatay(1,n,1,x,0);

}void queryy(int l,int r,int y,int x)

int mid = (l+r) >> 1;

queryy(l,mid,y<<1,x);

queryy(mid+1,r,y<<1|1,x);

}void queryx(int l,int r,int x)

int mid = (l+r) >> 1;

queryx(l,mid,x<<1);

queryx(mid+1,r,x<<1|1);

}int main()

}return 0;

}兩種方法單次操作的時間複雜度都是o(log^2),但第一種最差可以退化到o(n),此題第二種寫法就比第一種快了近5倍

HDU 4819 Mosaic 二維線段樹

題目大意 裸題,不解釋,上模板。比較省記憶體的寫法 hdu 4819 pragma comment linker,stack 102400000,102400000 include include include include include include include include inc...

hdu4819 Mosaic 二維線段樹(樹套樹)

題目描述 原問題中拆分出來這樣的乙個問題 給定乙個n n的矩陣,查詢某一塊最大最小值,修改某乙個位置的值,運算元共有約1e5次 思路 二維的線段樹,寫法是樹套樹,其中修改操作略微複雜,大致可以表述為先 沿x軸生長,每生長一點,就沿著y軸延展 pragma warning disable 4786 p...

HDU 4819 二維線段樹

13年長春現場賽的g題,赤裸裸的二維線段樹,單點更新,區間查詢 不過我是第一次寫二維的,一開始寫t了,原因是我沒有好好利用行段,說白一點,還是相當於枚舉行,然後對列進行線段樹,那要你寫二維線段樹幹嘛 二維就是在每個行段也建一棵樹,來代表這個區間的行裡的某些列的值 其他操作倒是不難,因為有一維的功底,...