HDU1754 I Hate It 线段树区间最值

题目链接:点击打开链接



代码1:

//线段树区间最值
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 200005

int num[maxn]; //纪录每个学生的成绩
struct segmentree
{
    int l; //左端点
    int r; //右端点
    int maxc; //区间内最大分数
};
segmentree tree[4*maxn]; //总线段长度为N,开数组的话一般开到N的4倍

inline int Max(int a, int b)
{
    return a > b ? a : b;
}
void build(int root,int l,int r) //root表示根节点,他的区间范围为[l,r]
{
    tree[root].l=l;
    tree[root].r=r;
    if(tree[root].l==tree[root].r) //左右端点相等时就说叶子节点
    {
        tree[root].maxc=num[l]; //赋初值
        return ;
    }
    int mid=(l+r)/2;
    build(root<<1,l,mid); //建立左孩子节点
    build(root<<1|1,mid+1,r); //root<<1|1相当于root*2+1;建立右孩子节点
    tree[root].maxc=Max(tree[root<<1].maxc,tree[root<<1|1].maxc); //更新父节点的maxc值
}

void update(int root,int pos,int v) //root是根节点,pos和v表示:更新pos处的值为v
{
    if(tree[root].l==tree[root].r&&tree[root].l==pos) //叶子节点既是pos对应的位置
    {
        tree[root].maxc=v;
        return ;
    }
    if(pos<=tree[root<<1].r)  //如果pos点是在root对应的左孩子的话,就在左孩子中找
      update(root<<1,pos,v);
    else update(root<<1|1,pos,v);
    tree[root].maxc=Max(tree[root<<1].maxc,tree[root<<1|1].maxc);  //更新父节点的maxc值
}

int query(int root,int l,int r) //询问[l,r]区间
{
    if(r<tree[root].l||l>tree[root].r)
      return 0;
    if(l<=tree[root].l&&r>=tree[root].r) //要查询的区间[l,r]包含root节点所表示的区间
     return tree[root].maxc;
    int mid=(tree[root].l+tree[root].r)/2;
    int a=query(root<<1,l,r);
    int b=query(root<<1|1,l,r);
    return max(a,b);
}

int main()
{
    int n,m,a,b;
    char str;
    while(scanf("%d%d",&n,&m)!=-1)
    {

        for(int i=1;i<=n;i++)
          scanf("%d",&num[i]);
        build(1,1,n); //构造线段树根节点为1,表示区间范围[1,maxn]
        while(m--)
        {
            getchar();
            scanf("%c%d%d",&str,&a,&b);
            if(str=='Q')
            {
                if(a>b) swap(a,b);
                printf("%d\n",query(1,a,b));
            }
            else if(str=='U')
            {
                num[a]=b;
                update(1,a,num[a]);
            }
        }
    }
    return 0;
}




代码2:

#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 200005

int num[maxn]; //纪录每个学生的成绩
struct segmentree
{
    int l; //左端点
    int r; //右端点
    int maxc; //区间内最大分数
};
segmentree tree[4*maxn]; //总线段长度为N,开数组的话一般开到N的4倍

void build(int root,int l,int r) //root表示根节点,他的区间范围为[l,r]
{
    tree[root].l=l;
    tree[root].r=r;
    if(tree[root].l==tree[root].r) //左右端点相等时就说叶子节点
    {
        tree[root].maxc=num[l]; //赋初值
        return ;
    }
    int mid=(l+r)/2;
    build(root<<1,l,mid); //建立左孩子节点
    build(root<<1|1,mid+1,r); //root<<1|1相当于root*2+1;建立右孩子节点
    tree[root].maxc=max(tree[root<<1].maxc,tree[root<<1|1].maxc); //更新父节点的maxc值
}

void update(int root,int pos,int v) //root是根节点,pos和v表示:更新pos处的值为v
{
    if(tree[root].l==tree[root].r) //叶子节点既是pos对应的位置
    {
        tree[root].maxc=v;
        return ;
    }
    int mid=(tree[root].l+tree[root].r)/2;
    if(pos<=mid)  //如果pos点是在root对应的左孩子的话,就在左孩子中找
      update(root<<1,pos,v);
    else update(root<<1|1,pos,v);
    tree[root].maxc=max(tree[root<<1].maxc,tree[root<<1|1].maxc);  //更新父节点的maxc值
}

int query(int root,int l,int r) //询问[l,r]区间
{
    if(l<=tree[root].l&&r>=tree[root].r) //要查询的区间[l,r]包含root节点所表示的区间
     return tree[root].maxc;
    int mid=(tree[root].l+tree[root].r)/2;
    int cnt;
    if(r<=mid) cnt=query(root<<1,l,r);
    else if(l>mid) cnt=query(root<<1|1,l,r);
    else cnt=max(query(root<<1,l,tree[root<<1].r),query(root<<1|1,tree[root<<1|1].l,r));
    return cnt;
}

int main()
{
    int n,m,a,b;
    char str;
    while(scanf("%d%d",&n,&m)!=-1)
    {

        for(int i=1;i<=n;i++)
          scanf("%d",&num[i]);
        build(1,1,maxn); //构造线段树根节点为1,表示区间范围[1,maxn]
        while(m--)
        {
            getchar();
            scanf("%c%d%d",&str,&a,&b);
            if(str=='Q')
            {
                if(a>b) swap(a,b);
                printf("%d\n",query(1,a,b));
            }
            else if(str=='U')
            {
                num[a]=b;
                update(1,a,num[a]);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(HDU1754 I Hate It 线段树区间最值)