某线段最值:
/* rmq:
ST:
minn[i][j]表示从第i个到i+(1<<j)-1的最小值
状态方程:minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1])
查询[l,r]区间时,区间个数是r-l+1,k为log2(r-l+1),那么最小值为minn[l][k],
因为log2(r-l+1)可能存在一点误差,即判断一下后端点
即min(minn[l][k],minn[r-(1<<k)+1][k])
最大值:
同理
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e5+7;
int minn[N][21],maxx[N][21],n;
int Log2[N];//表示log2(i)
void ST()
{
for(int i = 0; i <= n; i ++)Log2[i] = (i == 0 ? -1 : Log2[i >> 1] + 1);
for(int j=1;j<21;j++)
for(int i=1;i+(1<<j)<=n+1;i++)
{
minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
maxx[i][j]=max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]);
}
}
int query_min(int l,int r)
{
int k=Log2[r-l+1];
return min(minn[l][k],minn[r-(1<<k)+1][k]);
}
int query_max(int l,int r)
{
int k=Log2[r-l+1];
return max(maxx[l][k],maxx[r-(1<<k)+1][k]);
}
int main()
{
int q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&minn[i][0]);
maxx[i][0]=minn[i][0];
}
ST();
while(q--)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",query_max(l,r)-query_min(l,r));
}
return 0;
}
某矩阵最值
/*
二维的rmq可以将每一行看作是一维的rmq
maxx[i][j][k]表示: 第i行 [j,j+(1<<k)-1] 区间中的最大值
maxx[i][j][k]=max(maxx[i][j][k-1],maxx[i][j+(1<<(k-1))][k-1]);
该时间复杂度为:
建表:0(n*m*log(m))
查询:0(n)
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1e3+7;
const int inf=1e9+7;
int n,m;
int maxx[N][N][13],minn[N][N][13];
int Log2[N];
void ST()
{
for(int i = 0; i <= m; i ++)Log2[i] = (i == 0 ? -1 : Log2[i >> 1] + 1);
for(int i=1;i<=n;i++)
for(int k=1;k<13;k++)
for(int j=1;j+(1<<k)<=m+1;j++)
{
maxx[i][j][k]=max(maxx[i][j][k-1],maxx[i][j+(1<<(k-1))][k-1]);
minn[i][j][k]=min(minn[i][j][k-1],minn[i][j+(1<<(k-1))][k-1]);
}
}
int query_min(int lx,int ly,int rx,int ry)
{
int k=Log2[ry-ly+1];
int minn1=inf;
for(int i=lx;i<=rx;i++)
minn1=min(minn1,min(minn[i][ly][k],minn[i][ry-(1<<k)+1][k]));
return minn1;
}
int query_max(int lx,int ly,int rx,int ry)
{
int k=Log2[ry-ly+1];
int maxx1=-inf;
for(int i=lx;i<=rx;i++)
maxx1=max(maxx1,max(maxx[i][ly][k],maxx[i][ry-(1<<k)+1][k]));
return maxx1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&maxx[i][j][0]);
minn[i][j][0]=maxx[i][j][0];
}
ST();
int q;
scanf("%d",&q);
while(q--)
{
int lx,ly,rx,ry;
scanf("%d%d%d%d",&lx,&ly,&rx,&ry);
printf("%d %d\n",query_max(lx,ly,rx,ry),query_min(lx,ly,rx,ry));
}
return 0;
}