hdoj4819 [二維線段樹(線段樹套線段樹)]

傳送門
題意:有一個n*n的二維數組,q次詢問,每次詢問一個二維區間的最大最小值並且將二維區間的中心的值更改爲(最大值+最小值)/2
題解:rmq,如果不帶修改則可以用倍增求rmq,帶修改就用線段樹,一維如此,二維也是如此,做的第一道二維線段樹題,注意寫法

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
//#define debug(x) cout<<#x<<" is "<<x<<endl;
const int maxn=805;

int a[maxn][maxn],n,ac1,ac2;

struct nod{
    int rty;
    int maxxy;
    int minny;
};

struct Node{
    int rtx;
    struct nod y[maxn<<2];
}x[maxn<<2];

void pushupy(int rtx,int rty){
    x[rtx].y[rty].maxxy=max(x[rtx].y[rty<<1].maxxy,x[rtx].y[(rty<<1)|1].maxxy);
    x[rtx].y[rty].minny=min(x[rtx].y[rty<<1].minny,x[rtx].y[(rty<<1)|1].minny);
}

void buildy(int X,int rtx,int rt,int l,int r){
    if(l==r){
        if(X){
            x[rtx].y[rt].maxxy=x[rtx].y[rt].minny=a[X][l];
        }
        else{
            x[rtx].y[rt].maxxy=max(x[rtx<<1].y[rt].maxxy,x[(rtx<<1)|1].y[rt].maxxy);
            x[rtx].y[rt].minny=min(x[rtx<<1].y[rt].minny,x[(rtx<<1)|1].y[rt].minny);
        }
        return;
    }
    int mid=(l+r)>>1;
    buildy(X,rtx,rt<<1,l,mid);
    buildy(X,rtx,(rt<<1)|1,mid+1,r);
    pushupy(rtx,rt);
}



void buildx(int l,int r,int rt){
    if(l==r){
        buildy(l,rt,1,1,n);
        return;
    }
    int mid=(l+r)>>1;
    buildx(l,mid,rt<<1);
    buildx(mid+1,r,(rt<<1)|1);
    buildy(0,rt,1,1,n);
}

void updatey(int X,int Y,int rtx,int rt,int l,int r,int val){
    if(l==r){
        if(X){
            x[rtx].y[rt].maxxy=x[rtx].y[rt].minny=val;
        }
        else{
            x[rtx].y[rt].maxxy=max(x[rtx<<1].y[rt].maxxy,x[(rtx<<1)|1].y[rt].maxxy);
            x[rtx].y[rt].minny=min(x[rtx<<1].y[rt].minny,x[(rtx<<1)|1].y[rt].minny);
        }
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=Y)updatey(X,Y,rtx,rt<<1,l,mid,val);
    else updatey(X,Y,rtx,(rt<<1)|1,mid+1,r,val);
    pushupy(rtx,rt);
}

void updatex(int X,int Y,int rt,int l,int r,int val){
    if(l==r){
        updatey(l,Y,rt,1,1,n,val);
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=X)updatex(X,Y,rt<<1,l,mid,val);
    else updatex(X,Y,(rt<<1)|1,mid+1,r,val);
    updatey(0,Y,rt,1,1,n,val);
}

void queryy(int rtx,int y1,int y2,int rt,int l,int r){
    if(l>=y1&&r<=y2){
        ac1=max(x[rtx].y[rt].maxxy,ac1);
        ac2=min(x[rtx].y[rt].minny,ac2);
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=y1)queryy(rtx,y1,y2,rt<<1,l,mid);
    if(mid<y2)queryy(rtx,y1,y2,(rt<<1)|1,mid+1,r);
}

void queryx(int x1,int y1,int x2,int y2,int rt,int l,int r){
    if(l>=x1&&r<=x2){
        queryy(rt,y1,y2,1,1,n);
        return;
    }
    int mid=(l+r)>>1;
    if(mid>=x1)queryx(x1,y1,x2,y2,rt<<1,l,mid);
    if(mid<x2)queryx(x1,y1,x2,y2,(rt<<1)|1,mid+1,r);
}

int main(){
    int t;
    scanf("%d",&t);
    int Ca=0;
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&a[i][j]);
            }
        }
        buildx(1,n,1);
        int q;
        scanf("%d",&q);
        printf("Case #%d:\n",++Ca);
        while(q--){
            int b,c,d;
            scanf("%d%d%d",&b,&c,&d);
            int x1=max(1,b-d/2);
            int x2=min(n,b+d/2);
            int y1=max(1,c-d/2);
            int y2=min(n,c+d/2);
            ac1=0;
            ac2=0x3f3f3f3f;
            queryx(x1,y1,x2,y2,1,1,n);
            updatex(b,c,1,1,n,(ac1+ac2)/2);
            printf("%d\n",(ac1+ac2)/2);
        }
    }
    return 0;
}

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