HDU 4819 —— Mosaic(二维线段树)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4819


传说中长春赛区出现的很裸的二维线段树,从没写过二维的窝表示撸了一个晚上的代码,颤抖着点了个submit居然还特么地1Y了。。。

好吧,题意是给定一个初始的N*N矩阵以及每个方格的值,每次给出x, y, l,找到以(x,y)为中心的l*l大小的矩阵,l保证为奇数,找到这个矩阵中的最大值和最小值,然后求出它们的平均数,将(x,y)修改为平均数,并输出平均数。如果小矩阵有部分跑出大矩阵,跑出去的部分是忽略掉的。


感觉写得很搓的样子,貌似连所谓的懒惰标记都没有(虽然这题是单点更新,但重点是智商不够了= =)。

大概就是先按着X建立线段树,每个节点再建立Y的线段树。

查询和更新都是先按找X,然后找Y。


还是留个纪念吧。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 801
#define LEFT(o) ((o)<<1)
#define RIGHT(o) (((o)<<1)|1)
int t, n, q, x1, x2, y1, y2;
int map[N][N];
int lx[N<<2], rx[N<<2], ly[N<<2], ry[N<<2];
int A[N<<2][N<<2], B[N<<2][N<<2];
void maintain(int po, int o){
    A[po][o] = max(A[po][LEFT(o)], A[po][RIGHT(o)]);
    B[po][o] = min(B[po][LEFT(o)], B[po][RIGHT(o)]);
}
void buildY(int po, int o, int ll, int rr){
    ly[o]=ll; ry[o]=rr;
    if(ll<rr){
        int m = (ll+rr)>>1;
        buildY(po, LEFT(o), ll, m);
        buildY(po, RIGHT(o), m+1, rr);
        maintain(po, o);
    }
    else{
        if(lx[po]==rx[po]){
            A[po][o] = B[po][o] = map[lx[po]][ll];
        }
        else{
            A[po][o] = max(A[LEFT(po)][o], A[RIGHT(po)][o]);
            B[po][o] = min(B[LEFT(po)][o], B[RIGHT(po)][o]);
        }
    }
}
void buildX(int o, int ll, int rr){
    lx[o]=ll; rx[o]=rr;
    if(ll<rr){
        int m=(ll+rr)>>1;
        buildX(LEFT(o), ll, m);
        buildX(RIGHT(o), m+1, rr);
    }
    buildY(o, 1, 1, n);
}
void updateY(int po, int o, int ll, int rr, int v){
    //printf("UY: %d %d %d %d\n", lx[po], rx[po], ly[o], ry[o]);
    if(ly[o]==ry[o]){
        if(lx[po]==rx[po])  A[po][o] = B[po][o] = v;
        else{
            A[po][o] = max(A[LEFT(po)][o], A[RIGHT(po)][o]);
            B[po][o] = min(B[LEFT(po)][o], B[RIGHT(po)][o]);
        }
        return;
    }
    int m = (ly[o]+ry[o])>>1;
    if(rr<=m)   updateY(po, LEFT(o), ll, rr, v);
    else if(ll>m)   updateY(po, RIGHT(o), ll, rr, v);
    else{
        updateY(po, LEFT(o), ll, m, v);
        updateY(po, RIGHT(o), m+1, rr, v);
    }
    maintain(po, o);
}
void updateX(int o, int ll, int rr, int v){
    //printf("UX: %d %d\n", lx[o], rx[o]);
    if(lx[o]==rx[o]){
        updateY(o, 1, y1, y2, v);
        return;
    }
    int m = (lx[o]+rx[o])>>1;
    if(rr<=m)   updateX(LEFT(o), ll, rr, v);
    else if(ll>m)   updateX(RIGHT(o), ll, rr, v);
    else{
        updateX(LEFT(o), ll, m, v);
        updateX(RIGHT(o), m+1, rr, v);
    }
    updateY(o, 1, y1, y2, v);
}
void queryY(int po, int o, int ll, int rr, int& a,int& b){
   // printf("QY: %d %d %d %d\n", lx[po], rx[po], ly[o], ry[o]);
    if(ly[o]==ll && ry[o]==rr){
        a = A[po][o]; b = B[po][o];
      //  printf("bot: %d %d\n", a, b);
        return;
    }
    int m = (ly[o]+ry[o])>>1;
    int a1, a2, b1, b2;
    if(rr<=m)   queryY(po, LEFT(o), ll, rr, a1, b1);
    else if(ll>m)   queryY(po, RIGHT(o), ll, rr, a1, b1);
    else{
        queryY(po, LEFT(o), ll, m, a1, b1);
        queryY(po, RIGHT(o), m+1, rr, a2, b2);
        a1 = max(a1, a2);
        b1 = min(b1, b2);
    }
    a=a1; b=b1;
    //printf("%d %d : %d %d\n", ly[o], ry[o], a, b);
}
void queryX(int o, int ll, int rr, int& a, int& b){
    //printf("QX: %d %d\n", lx[o], rx[o]);
    if(lx[o]==ll && rx[o]==rr){
        queryY(o, 1, y1, y2, a, b);
        return;
    }
    int m = (lx[o]+rx[o])>>1;
    int a1, a2, b1, b2;
    if(rr<=m)   queryX(LEFT(o), ll, rr, a1, b1);
    else if(ll>m)   queryX(RIGHT(o), ll, rr, a1, b1);
    else{
        queryX(LEFT(o), ll, m, a1, b1);
        queryX(RIGHT(o), m+1, rr, a2, b2);
        a1 = max(a1, a2);
        b1 = min(b1, b2);
    }
    a=a1; b=b1;
}
int main(){
    scanf("%d", &t);
    for(int ct=1; ct<=t; ct++){
        scanf("%d", &n);
        for(int i=1;i<=n; i++){
            for(int j=1; j<=n; j++){
                scanf("%d", &map[i][j]);
            }
        }
        buildX(1, 1, n);
        scanf("%d", &q);
        printf("Case #%d:\n", ct);
        int x, y, l;
        while(q--){
            scanf("%d %d %d", &x, &y, &l);
            l>>=1;
            x1 = max(x-l, 1);
            x2 = min(x+l, n);
            y1 = max(y-l, 1);
            y2 = min(y+l, n);
            //printf("q: %d %d %d %d\n", x1, y1, x2, y2);
            int a, b;
            queryX(1, x1, x2, a, b);
           // printf("g: %d %d\n", a, b);
            a = (a+b)>>1;
            x1=x2=x; y1=y2=y;
            updateX(1, x1, x2, a);
            printf("%d\n", a);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值