标签:
二维线段树矩阵区间查询最大值
/*
矩阵求和预处理后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