[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;
}
View Code

 

posted @ 2020-03-24 15:12  _ZPENG  阅读(175)  评论(0编辑  收藏  举报