[UVA-11297]Census——二维线段树
Census
求矩形区域最大最小值,单点修改。
建立x方向的线段树,x方向线段树的每个节点都是一个y方向的线段树。查询复杂度log(n)*log(m),单点修改复杂度log(n)*log(m)。修改时对于x的叶节点和非叶节点需要区别对待。
#include<bits/stdc++.h> using namespace std; const int N=510; struct SegmentTree2D{ int Max[N*4][N*4],Min[N*4][N*4],n,m;//n:x范围,m:y轴范围 int ox,y1,y2,Mi,Ma,x,y,v;//一些用于询问修改的变量,避免传参太多 bool xleaf;//x方向是否为叶子 void updatey(int o,int ly,int ry){ if(ly==ry){ if(xleaf){Max[ox][o]=Min[ox][o]=v;return;} Max[ox][o]=max(Max[2*ox][o],Max[2*ox+1][o]); Min[ox][o]=min(Min[2*ox][o],Min[2*ox+1][o]); return; } int mid=(ly+ry)>>1,lc=2*o,rc=2*o+1; if(y<=mid)updatey(lc,ly,mid); else updatey(rc,mid+1,ry); Max[ox][o]=max(Max[ox][lc],Max[ox][rc]); Min[ox][o]=min(Min[ox][lc],Min[ox][rc]); } void updatex(int o,int lx,int rx){ if(lx==rx){ox=o;xleaf=true;updatey(1,1,m);return;} int mid=(lx+rx)>>1,lc=2*o,rc=2*o+1; if(x<=mid)updatex(lc,lx,mid); else updatex(rc,mid+1,rx); ox=o;xleaf=false; updatey(1,1,m);//非叶节点更新 } void update(int posx,int posy,int val){ x=posx;y=posy;v=val;updatex(1,1,n); } void queryy(int o,int y1,int y2,int ly,int ry){ if(y1<=ly&&y2>=ry){ Mi=min(Mi,Min[ox][o]); Ma=max(Ma,Max[ox][o]); return; } int mid=(ly+ry)>>1,lc=2*o,rc=2*o+1; if(y1<=mid)queryy(lc,y1,y2,ly,mid); if(y2>mid)queryy(rc,y1,y2,mid+1,ry); } void queryx(int o,int x1,int x2,int lx,int rx){ if(x1<=lx&&x2>=rx){ox=o;queryy(1,y1,y2,1,m);return;} int mid=(lx+rx)>>1,lc=2*o,rc=2*o+1; if(x1<=mid)queryx(lc,x1,x2,lx,mid); if(x2>mid)queryx(rc,x1,x2,mid+1,rx); } void query(int xa,int xb,int ya,int yb){ Mi=1e9;Ma=-1e9; y1=ya;y2=yb; queryx(1,xa,xb,1,n); } void buildy(int o,int ly,int ry){ if(ly==ry){ if(xleaf){ int v;scanf("%d",&v); Max[ox][o]=Min[ox][o]=v; return; } Max[ox][o]=max(Max[2*ox][o],Max[2*ox+1][o]); Min[ox][o]=min(Min[2*ox][o],Min[2*ox+1][o]); return; } int mid=(ly+ry)>>1,lc=2*o,rc=2*o+1; buildy(lc,ly,mid);buildy(rc,mid+1,ry); Max[ox][o]=max(Max[ox][lc],Max[ox][rc]); Min[ox][o]=min(Min[ox][lc],Min[ox][rc]); } void buildx(int o,int lx,int rx){ if(lx==rx){ox=o;xleaf=true; buildy(1,1,m);return;} int mid=(lx+rx)>>1,lc=2*o,rc=2*o+1; buildx(lc,lx,mid);buildx(rc,mid+1,rx); ox=o;xleaf=false; buildy(1,1,m); } }; SegmentTree2D T; int main(){ int n,v; scanf("%d",&n); T.n=T.m=n;T.buildx(1,1,n); int q;char op; scanf("%d",&q); while(q--){ int x1,x2,y1,y2; scanf(" %c",&op); if(op=='q'){ scanf("%d%d%d%d",&x1,&y1,&x2,&y2); T.query(x1,x2,y1,y2); printf("%d %d\n",T.Ma,T.Mi); }else{ scanf("%d%d%d",&x1,&y1,&x2); T.update(x1,y1,x2); } } return 0; }