題目鏈接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2272
題目描述:輸入一個矩陣,要求支持兩個操作,1. 查詢某個矩形區域內的最大值及最小值 2. 將 x y 位置的數改爲 v
解題思路:我是根據劉汝佳的白書上的說明做的這道題,以前從來不會二維線段樹,今天終於寫了一發,還是感覺常數比較大。。。雖然白書上說這種寫法已經很快了
建議自己寫一發,這樣才能清除具體的細節,不然只是知道大概是不行的
二維線段樹是一維線段樹的擴展,二維線段樹每個節點維護一棵線段樹。這樣對於一個x方向的節點,維護的線段樹是維護的從l 行到r 行的所有信息,在build 和update的時候要注意行方向的更新,詳見代碼!!
//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;
const int N = 505;
const int INF = 1000000000;
int a[N][N];
struct SegmentTree2D
{
int n,m;
int max_val[N<<2][N<<2],min_val[N<<2][N<<2];
int max_res,min_res;//-INF INF
int X1,X2,Y1,Y2,x,val,X,Y,xx;
bool isleaf;
void queryY(int k,int l,int r)
{
if(l>=Y1&&r<=Y2)
{
max_res=max(max_res,max_val[x][k]);
min_res=min(min_res,min_val[x][k]);
return;
}
int mid=(l+r)>>1;
if(Y1<=mid) queryY(lson,l,mid);
if(Y2>mid) queryY(rson,mid+1,r);
}
void queryX(int k,int l,int r)
{
if(l>=X1&&r<=X2)
{
x=k;
queryY(1,1,m);
return;
}
int mid=(l+r)>>1;
if(X1<=mid) queryX(lson,l,mid);
if(X2>mid) queryX(rson,mid+1,r);
}
void updateY(int k,int l,int r)
{
if(l==r)
{
if(isleaf)
max_val[x][k]=min_val[x][k]=val;
else
max_val[x][k]=max(max_val[x<<1][k],max_val[x<<1|1][k]), // x<<1 not lson!!!
min_val[x][k]=min(min_val[x<<1][k],min_val[x<<1|1][k]); // x<<1|1 not rson!!
return;
}
int mid=(l+r)>>1;
if(Y<=mid) updateY(lson,l,mid);
if(Y>mid) updateY(rson,mid+1,r);
max_val[x][k]=max(max_val[x][lson],max_val[x][rson]);
min_val[x][k]=min(min_val[x][lson],min_val[x][rson]);
}
void updateX(int k,int l,int r)
{
if(l==r)
{
x=k,isleaf=true;
updateY(1,1,m);
return;
}
int mid=(l+r)>>1;
if(X<=mid) updateX(lson,l,mid);
if(X>mid) updateX(rson,mid+1,r);
x=k,isleaf=false;
updateY(1,1,m);
}
void buildY(int k,int l,int r)
{
if(l==r)
{
if(isleaf)
max_val[x][k]=min_val[x][k]=a[xx][l];
else
max_val[x][k]=max(max_val[x<<1][k],max_val[x<<1|1][k]), // be careful
min_val[x][k]=min(min_val[x<<1][k],min_val[x<<1|1][k]); //
return;
}
int mid=(l+r)>>1;
buildY(lson,l,mid),buildY(rson,mid+1,r);
max_val[x][k]=max(max_val[x][lson],max_val[x][rson]);
min_val[x][k]=min(min_val[x][lson],min_val[x][rson]);
}
void buildX(int k,int l,int r)
{
if(l==r)
{
x=k,isleaf=true;
xx=l;
buildY(1,1,m);
return;
}
int mid=(l+r)>>1;
buildX(lson,l,mid),buildX(rson,mid+1,r);
x=k,isleaf=false;
buildY(1,1,m);
}
} tr;
int main()
{
#ifdef PKWV
freopen("in.in","r",stdin);
#endif // PKWV
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
tr.n=n,tr.m=m;
tr.buildX(1,1,n);
int Q;
scanf("%d",&Q);
while(Q--)
{
char ch[10];
scanf("%s",ch);
if(ch[0]=='q')
{
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
tr.max_res=-INF,tr.min_res=INF;
tr.X1=x1,tr.X2=x2,tr.Y1=y1,tr.Y2=y2;
tr.queryX(1,1,n);
printf("%d %d\n",tr.max_res,tr.min_res);
}else
{
int x,y,v;
scanf("%d%d%d",&x,&y,&v);
tr.X=x,tr.Y=y,tr.val=v;
tr.updateX(1,1,n);
}
}
return 0;
}