码迷,mamicode.com
首页 > 其他好文 > 详细

二维线段树

时间:2015-08-15 12:02:13      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:

二维线段树矩阵区间查询最大值
/*
矩阵求和预处理后O(1)就能算出来,不用线段树,除非有修改操作
*/

先第一维在第二维,注意建树有个顺序问题,
应该让第一维度的先建完然后再建第二个维度
具体看代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN=1005;
const int MAXM=1005;
struct node
{
    int l,r,max;
};
struct tree
{
    node sub[4*MAXM];//第二维
    int l,r;//第一维的左右,第一维度并不需要存最大值信息
}s[4*MAXN];
int a[MAXN][MAXM];
int suma[MAXN][MAXM]={0};

void build_(int l,int r,int x,int fax,int fal,int far)
{
    s[fax].sub[x].l=l;
    s[fax].sub[x].r=r;
    if (l==r)
    {
        if (fal==far)
            //这里是整个build的叶子节点
        else
            s[fax].sub[x].max=max(s[2*fax].sub[x].max,s[2*fax+1].sub[x].max);
            //由于第一维[fal,far]区间的子区间信息已经统计出来了,所以直接调用就好了
        return;
    }
    int mid=(l+r)>>1;
    build_(l,mid,2*x,fax,fal,far);
    build_(mid+1,r,2*x+1,fax,fal,far);
    s[fax].sub[x].max=max(s[fax].sub[2*x].max,s[fax].sub[2*x+1].max);
}
void build(int l,int r,int x,int l_,int r_)
{
    s[x].l=l;
    s[x].r=r;
    if (l==r)
    {
        build_(l_,r_,1,x,l,r);
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,2*x,l_,r_);
    build(mid+1,r,2*x+1,l_,r_);//先把第一维的子区间的信息算出来
    build_(l_,r_,1,x,l,r);//再算第一维对应的第二维的信息
}
int query_(int l,int r,int x,int fax)
{
    if (s[fax].sub[x].l==l&&s[fax].sub[x].r==r)
        return s[fax].sub[x].max;
    if (r<=s[fax].sub[2*x].r)
        return query_(l,r,2*x,fax);
    else if (l>=s[fax].sub[2*x+1].l)
        return query_(l,r,2*x+1,fax);
    else
        return max(query_(l,s[fax].sub[2*x].r,2*x,fax),query_(s[fax].sub[2*x+1].l,r,2*x+1,fax));
}
int query(int l,int r,int x,int l_,int r_)
{
    if (s[x].l==l&&s[x].r==r)
        return query_(l_,r_,1,x);
    if (r<=s[2*x].r)
        return query(l,r,2*x,l_,r_);
    else if (l>=s[2*x+1].l)
        return query(l,r,2*x+1,l_,r_);
    else
        return max(query(l,s[2*x].r,2*x,l_,r_),query(s[2*x+1].l,r,2*x+1,l_,r_));
}

int main()
{
    int i,j,m,n,T,l,r,l_,r_;
    cin>>n>>m;
    for (i=1;i<=n;i++)
        for (j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    build(1,n,1,1,m);
    cin>>T;
    while (T--)
    {
        scanf("%d%d%d%d",&l,&r,&l_,&r_);
        cout<<query(l,r,1,l_,r_)<<endl;
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

二维线段树

标签:

原文地址:http://blog.csdn.net/lanxuan365/article/details/47680161

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!