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;
}


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