Mosaic HDU

来源:互联网 发布:神盾阅读器软件 编辑:程序博客网 时间:2024/05/22 07:55

题目链接:Mosaic HDU - 4819

题目大意

一个n*n的矩阵, 让你求其中一个矩形区域中的最大值和最小值, 并更新其中的一个位置的值

思路

二维线段树

代码

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <set>#include <queue>#include <vector>using namespace std;const int maxn = 1e3 + 10, inf = 0x3f3f3f3f;int locx[maxn], locy[maxn];//x坐标和y坐标在线段树中对应的叶子节点的下标struct Nodey//代表一个点{    int l, r, ma, mi;};struct Nodex//代表一条x方向的一维线段树{    int l, r;    Nodey sty[maxn << 2];    void build(int rt, int L, int R)    {        sty[rt].l = L;        sty[rt].r = R;        sty[rt].ma = -inf;        sty[rt].mi = inf;        if (L == R)        {            locy[L] = rt;            return ;        }        int mid = (L + R) >> 1;        build(rt << 1, L, mid);        build((rt << 1) | 1, mid + 1, R);    }    int queryMin(int rt, int L, int R)    {        if (sty[rt].l == L && sty[rt].r == R)            return sty[rt].mi;        int mid = (sty[rt].l + sty[rt].r) >> 1;        if (mid < L) return queryMin((rt << 1) | 1, L, R);        else if (mid >= R) return queryMin(rt << 1, L, R);        else return min(queryMin((rt << 1) | 1, mid+1, R), queryMin(rt << 1, L, mid));    }    int queryMax(int rt, int L, int R)    {        if (sty[rt].l == L && sty[rt].r == R)            return sty[rt].ma;        int mid = (sty[rt].l + sty[rt].r) >> 1;        if (mid < L) return queryMax((rt << 1) | 1, L, R);        else if (mid >= R) return queryMax(rt << 1, L, R);        else return max(queryMax((rt << 1) | 1, mid+1, R), queryMax(rt << 1, L, mid));    }} stx[maxn << 2];int n;void build(int rt, int l, int r){    stx[rt].l = l;    stx[rt].r = r;    stx[rt].build(1, 1, n);    if (l == r)    {        locx[l] = rt;        return ;    }    int mid = (l + r) >> 1;    build(rt << 1, l, mid);    build((rt << 1) | 1, mid + 1, r);}void update(int x, int y, int v){    x = locx[x], y = locy[y];    stx[x].sty[y].mi = stx[x].sty[y].ma = v;    for (int i = x; i; i >>= 1)    {        for (int j = y; j; j >>= 1)        {            if (i == x && j == y) continue;            if (j == y) // x, y -> 2x, y, when double the length of x            {                stx[i].sty[j].mi = min(stx[i << 1].sty[j].mi, stx[(i << 1) | 1].sty[j].mi);                stx[i].sty[j].ma = max(stx[i << 1].sty[j].ma, stx[(i << 1) | 1].sty[j].ma);            }            else            {                stx[i].sty[j].mi = min(stx[i].sty[j << 1].mi, stx[i].sty[(j << 1) | 1].mi);                stx[i].sty[j].ma = max(stx[i].sty[j << 1].ma, stx[i].sty[(j << 1) | 1].ma);            }        }    }}int queryMin(int rt, int x1, int x2, int y1, int y2){    if (stx[rt].l == x1 && stx[rt].r == x2)        return stx[rt].queryMin(1, y1, y2);    int mid = (stx[rt].l + stx[rt].r) >> 1;    if (x1 > mid) return queryMin((rt << 1) | 1, x1, x2, y1, y2);    else if (x2 <= mid) return queryMin(rt << 1, x1, x2, y1, y2);    else return min(queryMin((rt << 1) | 1, mid+1, x2, y1, y2),                        queryMin(rt << 1, x1, mid, y1, y2));}int queryMax(int rt, int x1, int x2, int y1, int y2){    if (stx[rt].l == x1 && stx[rt].r == x2)        return stx[rt].queryMax(1, y1, y2);    int mid = (stx[rt].l + stx[rt].r) >> 1;    if (x1 > mid) return queryMax((rt << 1) | 1, x1, x2, y1, y2);    else if (x2 <= mid) return queryMax(rt << 1, x1, x2, y1, y2);    else return max(queryMax((rt << 1) | 1, mid+1, x2, y1, y2),                        queryMax(rt << 1, x1, mid, y1, y2));}int main(){    int T, cas = 1;    for (scanf("%d", &T); T; --T)    {        printf("Case #%d:\n", cas++);        scanf("%d", &n);        build(1, 1, n);        for (int i = 1; i <= n; ++i)        {            for (int j = 1; j <= n; ++j)            {                int t;                scanf("%d", &t);                update(i, j, t);            }        }        int q, x, y, L;        scanf("%d", &q);        while (q--)        {            scanf("%d%d%d", &x, &y, &L);            int x1 = max(x - L / 2, 1);            int x2 = min(x + L / 2, n);            int y1 = max(y - L / 2, 1);            int y2 = min(y + L / 2, n);            int Max = queryMax(1, x1, x2, y1, y2);            int Min = queryMin(1, x1, x2, y1, y2);            int t = (Max + Min) / 2;            printf("%d\n", t);            update(x, y, t);        }    }    return 0;}

网上的一个模板

struct Nodey {    int ly, ry, val, Max, Min, sum;//元素 最大值 最小值 元素和};int nx, ny;//横长 竖长int posx[MAXN], posy[MAXN];struct Nodex {    int lx, rx;    Nodey treey[MAXN<<2];    void Build_y(int o, int l, int r) {        treey[o].ly = l; treey[o].ry = r;        treey[o].Max = 0; treey[o].Min = INF;        treey[o].sum = 0; treey[o].val = 0;        if(l == r) {            posy[l] = o;            return ;        }        int mid = (l + r) >> 1;        Build_y(ll, l, mid);        Build_y(rr, mid+1, r);    }    int Query_y(int o, int y1, int y2, int op) {        if(treey[o].ly == y1 && treey[o].ry == y2) {            if(op == 0) return treey[o].Max;            if(op == 1) return treey[o].Min;            if(op == 2) return treey[o].sum;        }        int mid = (treey[o].ly + treey[o].ry) >> 1;        if(y2 <= mid) return Query_y(ll, y1, y2, op);        else if(y1 > mid) return Query_y(rr, y1, y2, op);        else {            if(op == 0) return max(Query_y(ll, y1, mid, op), Query_y(rr, mid+1, y2, op));            if(op == 1) return min(Query_y(ll, y1, mid, op), Query_y(rr, mid+1, y2, op));            if(op == 2) return Query_y(ll, y1, mid, op) + Query_y(rr, mid+1, y2, op);        }    }};Nodex treex[MAXN<<2];void Build_x(int o, int l, int r) {    treex[o].lx = l; treex[o].rx = r;    treex[o].Build_y(1, 1, ny);    if(l == r) {        posx[l] = o;        return ;    }    int mid = (l + r) >> 1;    Build_x(ll, l, mid);    Build_x(rr, mid+1, r);}int Query_x(int o, int x1, int x2, int y1, int y2, int op) {    if(treex[o].lx == x1 && treex[o].rx == x2) {        return treex[o].Query_y(1, y1, y2, op);    }    int mid = (treex[o].lx + treex[o].rx) >> 1;    if(x2 <= mid) return Query_x(ll, x1, x2, y1, y2, op);    else if(x1 > mid) return Query_x(rr, x1, x2, y1, y2, op);    else {        if(op == 0) return max(Query_x(ll, x1, mid, y1, y2, op), Query_x(rr, mid+1, x2, y1, y2, op));        if(op == 1) return min(Query_x(ll, x1, mid, y1, y2, op), Query_x(rr, mid+1, x2, y1, y2, op));        if(op == 2) return Query_x(ll, x1, mid, y1, y2, op) + Query_x(rr, mid+1, x2, y1, y2, op);    }}void PushUpy(int x, int y) {    treex[x].treey[y].Max = max(treex[x].treey[y<<1].Max, treex[x].treey[y<<1|1].Max);    treex[x].treey[y].Min = min(treex[x].treey[y<<1].Min, treex[x].treey[y<<1|1].Min);    treex[x].treey[y].sum = treex[x].treey[y<<1].sum + treex[x].treey[y<<1|1].sum;}void PushUpx(int x, int y) {    treex[x].treey[y].Max = max(treex[x<<1].treey[y].Max, treex[x<<1|1].treey[y].Max);    treex[x].treey[y].Min = min(treex[x<<1].treey[y].Min, treex[x<<1|1].treey[y].Min);    treex[x].treey[y].sum = treex[x<<1].treey[y].sum + treex[x<<1|1].treey[y].sum;}void Change(int x, int y, int v) {    treex[x].treey[y].Max = v;    treex[x].treey[y].Min = v;    treex[x].treey[y].sum = v;    treex[x].treey[y].val = v;}void Update(int x, int y, int v) {//单点更新    for(int i = posx[x]; i ; i >>= 1) {        for(int j = posy[y]; j ; j >>= 1) {            if(i == posx[x] && j == posy[y]) {                Change(posx[x], posy[y], v);                continue;            }            PushUpy(i, j);        }        if(i == posx[x]) continue;        for(int j = posy[y]; j ; j >>= 1) {            PushUpx(i, j);        }    }}int Sum(int x, int y) {//求 (x, y)对应节点到根路径的元素之和    int sum = 0;    for(int i = posx[x]; i ; i >>= 1) {        for(int j = posy[y]; j ; j >>= 1) {            sum += treex[i].treey[j].val;        }    }    return sum;}
原创粉丝点击