Uva 11297 Census(线段树)

本文介绍了一道关于二维线段树的经典算法题目。通过详细的代码实现,讲解了如何利用二维线段树进行区间查询及更新操作,适用于解决矩阵范围内最大值与最小值的查询问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给一个n*n的矩阵,给出q个操作,操作有两种,一种是查询 矩阵内x1 <= x <= x2, y1 <= y <= y2的最大值和最小值,另一种是把(x, y)位置的值改为v


思路:二维线段树的模板题


#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
const int INF = 1 << 30;
const int maxn = 2010;
using namespace std;

int Max[maxn][maxn], Min[maxn][maxn];
int xo, xleaf, x1, y1, x2, y2;
int x, y, v, vmax, vmin, n, m, q;
char op[5];

void query1D(int node, int l, int r) {
    if(l >= y1 && r <= y2) {
        vmax = max(vmax, Max[xo][node]);
        vmin = min(vmin, Min[xo][node]);
    } else {
        int mid = (l + r) >> 1;
        if(y1 <= mid) query1D(node * 2, l, mid);
        if(y2 > mid) query1D(node * 2 + 1, mid + 1, r);
    }
}

void query2D(int node, int l, int r) {
    if(l >= x1 && r <= x2) { xo = node; query1D(1, 1, m); }
    else {
        int mid = (l + r) >> 1;
        if(x1 <= mid) query2D(node * 2, l, mid);
        if(x2 > mid) query2D(node * 2 + 1, mid + 1, r);
    }
}

void update1D(int node, int l, int r) {
    if(l == r) {
        if(xleaf) { Max[xo][node] = Min[xo][node] = v; return; }
        Max[xo][node] = max(Max[xo * 2][node], Max[xo * 2 + 1][node]);
        Min[xo][node] = min(Min[xo * 2][node], Min[xo * 2 + 1][node]);
    } else {
        int mid = (l + r) >> 1;
        if(y <= mid) update1D(node * 2, l, mid);
        else update1D(node * 2 + 1, mid + 1, r);
        Max[xo][node] = max(Max[xo][node * 2], Max[xo][node * 2 + 1]);
        Min[xo][node] = min(Min[xo][node * 2], Min[xo][node * 2 + 1]);
    }
}

void update2D(int node, int l, int r) {
    if(l == r) {
        xo = node; xleaf = 1;
        update1D(1, 1, m);
    } else {
        int mid = (l + r) >> 1;
        if(x <= mid) update2D(node * 2, l, mid);
        else update2D(node * 2 + 1, mid + 1, r);
        xo = node; xleaf = 0;
        update1D(1, 1, m);
    }
}

int main() {
    while(scanf("%d", &n) != EOF) {
        m = n;
        for(x = 1; x <= n; x++) {
            for(y = 1; y <= m; y++) {
                scanf("%d", &v);
                update2D(1, 1, n);
            }
        }
        scanf("%d", &q);
        while(q--) {
            scanf("%s", op);
            if(op[0] == 'q') {
                scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
                vmax = -INF; vmin = INF;
                query2D(1, 1, n);
                printf("%d %d\n", vmax, vmin);
            } else {
                scanf("%d %d %d", &x, &y, &v);
                update2D(1, 1, n);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值