一般用来求区间最大值最小值的:
#include
#include
using namespace std;
const int maxn=10010;
int a[maxn];
struct node
{
int left,right,min,max;
}num[maxn<<2];
int buildmin(int left,int right,int cnt)
{
int mid;
num[cnt].left=left;
num[cnt].right=right;
if(left==right)
return num[cnt].min=a[left];
mid=(left+right)>>1;
return num[cnt].min=min(buildmin(left,mid,cnt*2),buildmin(mid+1,right,cnt*2+1));
}
int buildmax(int left,int right,int cnt)
{
int mid;
num[cnt].left=left;
num[cnt].right=right;
if(left==right)
return num[cnt].max=a[left];
mid=(left+right)>>1;
return num[cnt].max=max(buildmax(left,mid,cnt*2),buildmax(mid+1,right,cnt*2+1));
}
int querymin(int left,int right,int cnt)
{
int mid;
if(left==num[cnt].left&&right==num[cnt].right)
return num[cnt].min;
mid=(num[cnt].left+num[cnt].right)>>1;
if(right<=mid)
return querymin(left,right,cnt*2);
else if(left>mid)
return querymin(left,right,cnt*2+1);
else
return min(querymin(left,mid,cnt*2),querymin(mid+1,right,cnt*2+1));
}
int querymax(int left,int right,int cnt)
{
int mid;
if(left==num[cnt].left&&right==num[cnt].right)
return num[cnt].max;
mid=(num[cnt].left+num[cnt].right)>>1;
if(right<=mid)
return querymax(left,right,cnt*2);
else if(left>mid)
return querymax(left,right,cnt*2+1);
else
return max(querymax(left,mid,cnt*2),querymax(mid+1,right,cnt*2+1));
}
如果不仅要求区间最大值/最小值的位置,还要得到它的下标,那就维护的时候带上下标和最值一起,返回类型为pair
typedef long long LL;
const int MAXN=100000+5;
LL a[MAXN];
struct node
{
int id;
int left,right;
LL min;
}num[MAXN*4];
//建树
pair<int,LL> buildmin(int left,int right,int cnt)
{
int mid;
num[cnt].left=left;
num[cnt].right=right;
if(left==right)
{
num[cnt].id=left;
num[cnt].min=a[left];
return make_pair(left,a[left]);
}
mid=(left+right)>>1;
pair<int,LL> r1=buildmin(left,mid,cnt*2);
pair<int,LL> r2=buildmin(mid+1,right,cnt*2+1);
if(r1.secondmin=r1.second;
return r1;
}
else
{
num[cnt].id=r2.first;
num[cnt].min=r2.second;
return r2;
}
}
//返回pair类型,first为下标,second为最小值
pair<int,LL> querymin(int left,int right,int cnt)
{
int mid;
if(left==num[cnt].left&&right==num[cnt].right)
return make_pair(num[cnt].id,num[cnt].min);
mid=(num[cnt].left+num[cnt].right)>>1;
if(right<=mid)
return querymin(left,right,cnt*2);
else if(left>mid)
return querymin(left,right,cnt*2+1);
else
{
pair<int,LL> r1=querymin(left,mid,cnt*2);
pair<int,LL> r2=querymin(mid+1,right,cnt*2+1);
return r1.second