Mosaic HDU - 4819

点击打开链接

二维线段树模板题 二维与一维线段树都是一个道理 即把大的区域或区间分成更小的部分 难在理解二维中大区域和小区域之间的关系

可以当作树套树来想 二维中每个小区间都代表一棵一维线段树 确定二维中每一个小区间就是确定了一个区域有哪些行 再确定对应一维线段树中某个区间 就是确定了一个区域有哪些列

 

#include 
#include 
#include 
using namespace std;
#define N 0x3f3f3f3f

int minn[4010][4010],maxx[4010][4010];
int n,minnn,maxxx;

void pushupy(int curx,int cury)
{
    minn[curx][cury]=min(minn[curx][cury*2],minn[curx][cury*2+1]);
    maxx[curx][cury]=max(maxx[curx][cury*2],maxx[curx][cury*2+1]);
    return;
}

void pushupxI(int l,int r,int curx,int cury)
{
    int m;
    minn[curx][cury]=min(minn[curx*2][cury],minn[curx*2+1][cury]);
    maxx[curx][cury]=max(maxx[curx*2][cury],maxx[curx*2+1][cury]);
    if(l==r) return;
    m=(l+r)/2;
    pushupxI(l,m,curx,cury*2);
    pushupxI(m+1,r,curx,cury*2+1);
    return;
}

void pushupxII(int tary,int l,int r,int curx,int cury)
{
    int m;
    minn[curx][cury]=min(minn[curx*2][cury],minn[curx*2+1][cury]);
    maxx[curx][cury]=max(maxx[curx*2][cury],maxx[curx*2+1][cury]);
    if(l==r) return;
    m=(l+r)/2;
    if(tary<=m) pushupxII(tary,l,m,curx,cury*2);
    else pushupxII(tary,m+1,r,curx,cury*2+1);
    return;
}

void buildy(int l,int r,int curx,int cury)
{
    int m,t;
    if(l==r)
    {
        scanf("%d",&t);
        minn[curx][cury]=t;
        maxx[curx][cury]=t;
        return;
    }
    m=(l+r)/2;
    buildy(l,m,curx,cury*2);
    buildy(m+1,r,curx,cury*2+1);
    pushupy(curx,cury);
    return;
}

void buildx(int l,int r,int curx)
{
    int m;
    if(l==r)
    {
        buildy(1,n,curx,1);
        return;
    }
    m=(l+r)/2;
    buildx(l,m,curx*2);
    buildx(m+1,r,curx*2+1);
    pushupxI(1,n,curx,1);
    return;
}

void queryy(int yl,int yr,int l,int r,int curx,int cury)
{
    int m;
    if(yl<=l&&r<=yr)
    {
        minnn=min(minnn,minn[curx][cury]);
        maxxx=max(maxxx,maxx[curx][cury]);
        return;
    }
    m=(l+r)/2;
    if(yl<=m) queryy(yl,yr,l,m,curx,cury*2);
    if(yr>=m+1) queryy(yl,yr,m+1,r,curx,cury*2+1);
    return;
}

void queryx(int xl,int xr,int yl,int yr,int l,int r,int curx)
{
    int m,res;
    if(xl<=l&&r<=xr)
    {
        queryy(yl,yr,1,n,curx,1);
        return;
    }
    m=(l+r)/2;
    if(xl<=m) queryx(xl,xr,yl,yr,l,m,curx*2);
    if(xr>=m+1) queryx(xl,xr,yl,yr,m+1,r,curx*2+1);
    return;
}

void updatey(int tary,int val,int l,int r,int curx,int cury)
{
    int m;
    if(l==r)
    {
        minn[curx][cury]=val;
        maxx[curx][cury]=val;
        return;
    }
    m=(l+r)/2;
    if(tary<=m) updatey(tary,val,l,m,curx,cury*2);
    else updatey(tary,val,m+1,r,curx,cury*2+1);
    pushupy(curx,cury);
    return;
}

void updatex(int tarx,int tary,int val,int l,int r,int curx)
{
    int m;
    if(l==r)
    {
        updatey(tary,val,1,n,curx,1);
        return;
    }
    m=(l+r)/2;
    if(tarx<=m) updatex(tarx,tary,val,l,m,curx*2);
    else updatex(tarx,tary,val,m+1,r,curx*2+1);
    pushupxII(tary,1,n,curx,1);
    return;
}

int main()
{
    int t,cas,i,j,q,x,y,l,val;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        scanf("%d",&n);
        for(i=1;i<=4*n;i++)
        {
            for(j=1;j<=4*n;j++)
            {
                minn[i][j]=N;
                maxx[i][j]=-N;
            }
        }
        buildx(1,n,1);
        scanf("%d",&q);
        printf("Case #%d:\n",cas);
        while(q--)
        {
            scanf("%d%d%d",&x,&y,&l);
            minnn=N,maxxx=-N;
            queryx(max(1,x-l/2),min(n,x+l/2),max(1,y-l/2),min(n,y+l/2),1,n,1);
            val=(minnn+maxxx)/2;
            updatex(x,y,val,1,n,1);
            printf("%d\n",val);
        }
    }
    return 0;
}

 

 

 

 

你可能感兴趣的:(线段树/树状数组/RMQ)