HDU 4819 Mosaic 二维线段树

【题目大意】

裸题,不解释,上模板。


比较省内存的写法:

/* HDU 4819 */
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF = 1000111222;
const double INFF = 1e100;
const double eps = 1e-8;
const LL mod = 10000000007LL;
const int NN = 810;
const int MM = 400010;
/* ****************** */

int m_a[NN*2][NN*2];
int m_i[NN*2][NN*2];
int ans_max, ans_min;
int X1, Y1, X2, Y2, X, Y;
//为了函数的参数不过于冗杂,我把修改和查询的变量改为全局的
int col; //单点修改值,为了模板的移植性,把这个设置为全局变量

inline int MID(int x,int y)
{
    return (x + y) >> 1;
}
inline int loc(int l,int r)
{
    return (l + r) | !(l==r);
}
inline int ls(int l,int r)
{
    return loc(l, MID(l, r));
}
inline int rs(int l,int r)
{
    return loc(MID(l, r) + 1, r);
}
void update1D(int st,int en,int l,int r)
{
    int R1 = loc(st, en);
    int R2 = loc(l, r);
    if (l == r)
    {
        if (st == en)
        {
            //这个是一个点,直接修改
            m_a[R1][R2] = m_i[R1][R2] = col;
            return;
        }
        //虽然这个在辅线段树中是一个点,但是在主线段树中不是一个点
        //所幸的是,主线段中对应的下方节点是修改好了的,所以利用主线段树修改
        int R1_lson = ls(st, en);
        int R1_rson = rs(st, en);
        m_a[R1][R2] = max(m_a[R1_lson][R2], m_a[R1_rson][R2]);
        m_i[R1][R2] = min(m_i[R1_lson][R2], m_i[R1_rson][R2]);
    }
    else
    {
        //这部分和一维线段树的基础操作类似
        int mid = MID(l, r);
        if (Y <= mid)
            update1D(st, en, l, mid);
        else
            update1D(st, en, mid + 1, r);
        int R2_lson = ls(l, r);
        int R2_rson = rs(l, r);
        m_a[R1][R2] = max(m_a[R1][R2_lson], m_a[R1][R2_rson]);
        m_i[R1][R2] = min(m_i[R1][R2_lson], m_i[R1][R2_rson]);
    }
}
void update2D(int st,int en,int l,int r)
{
    if (st == en)
    {
        update1D(st, en, l, r);
    }
    else
    {
        int mid = MID(st, en);
        if (X <= mid)
            update2D(st, mid, l, r);
        else
            update2D(mid+1, en, l, r);
        update1D(st, en, l, r);
    }
}
void query1D(int st,int en,int l,int r)
{
    if (Y1 <= l && r <= Y2)
    {
        int R1 = loc(st, en);
        int R2 = loc(l, r);
        ans_max = max(ans_max, m_a[R1][R2]);
        ans_min = min(ans_min, m_i[R1][R2]);
    }
    else
    {
        int mid = MID(l, r);
        if (Y1 <= mid)
            query1D(st, en, l, mid);
        if (Y2 >= mid + 1)
            query1D(st, en, mid + 1, r);
    }
}
void query2D(int st,int en,int l,int r)
{
    if (X1 <= st && en <= X2)
    {
        query1D(st, en, l, r);
    }
    else
    {
        int mid = MID(st, en);
        if (X1 <= mid)
            query2D(st, mid, l, r);
        if (X2 >= mid + 1)
            query2D(mid + 1, en, l, r);
    }
}

int main()
{
    int cas, ee = 0;
    int i, j, n, m, x, y, z;
    scanf("%d", &cas);
    while (cas--)
    {
        printf("Case #%d:\n", ++ee);
        scanf("%d", &n);
        for (i = 1; i <= n; i ++)
            for (j = 1; j <= n; j ++)
            {
                scanf("%d", &col);
                X = i;
                Y = j;
                update2D(1, n, 1, n);
            }
        scanf("%d", &m);
        for (i = 0; i < m; i ++)
        {
            scanf("%d%d%d", &x, &y, &z);
            X1 = max(1, x - z/2);
            X2 = min(n, x + z/2);
            Y1 = max(1, y - z/2);
            Y2 = min(n, y + z/2);
            ans_max = -INF;
            ans_min = INF;
            query2D(1, n, 1, n);
          //  cout<<"max=="<<ans_max<<endl;
          //  cout<<"min=="<<ans_min<<endl;
            col = (ans_max + ans_min)/2;
            printf("%d\n", col);
            X = x;
            Y = y;
            update2D(1, n, 1, n);
        }
    }
    return 0;
}

一般的写法:

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF = 1000111222;
const double INFF = 1e100;
const double eps = 1e-8;
const LL mod = 10000000007LL;
const int NN = 810;
const int MM = 400010;
/* ****************** */

int m_a[NN*4][NN*4];
int m_i[NN*4][NN*4];
int ans_max, ans_min;
int X1, Y1, X2, Y2, X, Y;
bool leaf;
//为了函数的参数不过于冗杂,我把修改和查询的变量改为全局的
int col; //单点修改值,为了模板的移植性,把这个设置为全局变量

inline int MID(int x,int y)
{
    return (x + y) >> 1;
}
void update1D(int R1,int R2,int l,int r)
{
    if (l == r)
    {
        if (leaf)
        {
            //这个是一个点,直接修改
            m_a[R1][R2] = m_i[R1][R2] = col;
            return;
        }
        //虽然这个在辅线段树中是一个点,但是在主线段树中不是一个点
        //所幸的是,主线段中对应的下方节点是修改好了的,所以利用主线段树修改
        m_a[R1][R2] = max(m_a[R1<<1][R2], m_a[R1<<1|1][R2]);
        m_i[R1][R2] = min(m_i[R1<<1][R2], m_i[R1<<1|1][R2]);
    }
    else
    {
        //这部分和一维线段树的基础操作类似
        int mid = MID(l, r);
        if (Y <= mid)
            update1D(R1, R2<<1, l, mid);
        else
            update1D(R1, R2<<1|1, mid + 1, r);
        m_a[R1][R2] = max(m_a[R1][R2<<1], m_a[R1][R2<<1|1]);
        m_i[R1][R2] = min(m_i[R1][R2<<1], m_i[R1][R2<<1|1]);
    }
}
void update2D(int R1,int st,int en,int l,int r)
{
    if (st == en)
    {
        leaf = true;
        update1D(R1, 1, l, r);
    }
    else
    {
        int mid = MID(st, en);
        if (X <= mid)
            update2D(R1<<1, st, mid, l, r);
        else
            update2D(R1<<1|1, mid+1, en, l, r);
        leaf = false;
        update1D(R1, 1, l, r);
    }
}
void query1D(int R1,int R2,int l,int r)
{
    if (Y1 <= l && r <= Y2)
    {
        ans_max = max(ans_max, m_a[R1][R2]);
        ans_min = min(ans_min, m_i[R1][R2]);
    }
    else
    {
        int mid = MID(l, r);
        if (Y1 <= mid)
            query1D(R1, R2<<1, l, mid);
        if (Y2 >= mid + 1)
            query1D(R1, R2<<1|1, mid + 1, r);
    }
}
void query2D(int R1,int st,int en,int l,int r)
{
    if (X1 <= st && en <= X2)
    {
        query1D(R1, 1, l, r);
    }
    else
    {
        int mid = MID(st, en);
        if (X1 <= mid)
            query2D(R1<<1, st, mid, l, r);
        if (X2 >= mid + 1)
            query2D(R1<<1|1, mid + 1, en, l, r);
    }
}

int main()
{
    int cas, ee = 0;
    int i, j, n, m, x, y, z;
    scanf("%d", &cas);
    while (cas--)
    {
        printf("Case #%d:\n", ++ee);
        scanf("%d", &n);
        for (i = 1; i <= n; i ++)
            for (j = 1; j <= n; j ++)
            {
                scanf("%d", &col);
                X = i;
                Y = j;
                update2D(1, 1, n, 1, n);
            }
        scanf("%d", &m);
        for (i = 0; i < m; i ++)
        {
            scanf("%d%d%d", &x, &y, &z);
            X1 = max(1, x - z/2);
            X2 = min(n, x + z/2);
            Y1 = max(1, y - z/2);
            Y2 = min(n, y + z/2);
            ans_max = -INF;
            ans_min = INF;
            query2D(1, 1, n, 1, n);
          //  cout<<"max=="<<ans_max<<endl;
          //  cout<<"min=="<<ans_min<<endl;
            col = (ans_max + ans_min)/2;
            printf("%d\n", col);
            X = x;
            Y = y;
            update2D(1, 1, n, 1, n);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值