uva 11297 Census

题目链接: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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章