模板:线段树求区间最大/最小值及下标

一般用来求区间最大值最小值的:

#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

你可能感兴趣的:(总结)