hdu 1754 线段树入门的题

以前只听说过线段树却并没有真正的写过

题目是中文的就不说了很明显是线段树的题,细节见代码的注释

貌似注释太多也不好看了,就再附上一个无注释的版本,哈哈。。

#include<algorithm>
#include<cstdio>
#define maxn 200005
struct point
{
    int left,right,mavalue;
}node[3*maxn];//这个树并没有记录左右儿子的位置,而是直根据二叉树u的左儿子为2*u 右儿子为2*n+1来生成的,但是是有点浪费空间的
int score[maxn];//记录初始时学生的分数
void buildtree(int left,int right,int u)//初始的构建树的函数 left 和right 分别为当前这棵树的区间范围,此树我用的是闭区间,一般是用半开办闭的区间,u是当前这棵树的根
{
    node[u].left=left;//给区间左端赋值
    node[u].right=right;// 给区间右端赋值
    if(left==right) node[u].mavalue=score[left]; //当区间长度为一时区间最大值即为其对应的一个分数的值
    else//当区间的长度大于一时,递归构建子树
    {
        buildtree(left,(left+right)/2,2*u); //递归构建左子树
        buildtree(((left+right)/2)+1,right,2*u+1);//递归构建右子树
        node[u].mavalue=std::max(node[2*u].mavalue,node[2*u+1].mavalue);//更新区间的最大值为左右子树的区间最大值的大的值
    }
};
void updata(int stu,int val,int u)//修改操作,修改某个学生的分数,亦要更新包含它的区间的最大值
{
    node[u].mavalue=std::max(val,node[u].mavalue);//更新当前这棵树的所包含的区间的最大值
    if(node[u].left==node[u].right) return;//区间长度为1了说明修改完成了
    if(stu<=node[2*u].right) updata(stu,val,2*u);//如果stu被包含在左树中就去修改左子树
    else updata(stu,val,2*u+1);//反之修改右子树
}
int query(int left,int right,int u)//查询操作,找到在在闭区间[left,right]内的最大值
{
    if(node[u].left==left&&node[u].right==right) return node[u].mavalue;//刚好找到了这个区间则这个区间的最大值即为答案
    if(right<=node[2*u].right) return query(left,right,2*u);//在左子树中找到了包含这个区间的区间,
    if(left>=node[2*u+1].left) return query(left,right,2*u+1);//在右子树中找到了包含这个区间的区间,则去这个区间去找
    //在没找到包含我们要查找的区间的区间时,就把我们把当前的区间二分,取二分区间的最大值为我们要的答案
    int mid=(node[u].left+node[u].right)/2;//注意二分的是当前区间,而不是查找的区间。再根据二分出的中值把我们要查找的区间,分成2部分
    return  std::max(query(left,mid,2*u),query(mid+1,right,2*u+1));//把要查找的区间分成2部分后,再去左右子树中去分别去查找2部分区间的最大值
}
int main()
{
    int n,m,s,e;char temp,c;
    while(scanf("%d%c%d%c",&n,&temp,&m,&temp)!=EOF)//读入数据可能我这样读入有点奇葩,不过能AC就行
    {
        for(int i=1;i<=n;i++)
            scanf("%d%c",&score[i],&temp);

        buildtree(1,n,1);
        for(int i=0;i<m;i++)
        {
            scanf("%c",&c);
            scanf("%c%d%c%d%c",&temp,&s,&temp,&e,&temp);//读入的时候要保证c读到的是字母而不是空格或回车
            if(c=='U')
                updata(s,e,1);
            if(c=='Q')
                printf("%d\n",query(s,e,1));
        }
    }
    return 0;
}

其实由于第一次写代码大部分框架也是源于网络,但是在我完全弄懂了以后再修改,写注释的。。。。

#include<algorithm>
#include<cstdio>
#define maxn 200005
struct point
{
    int left,right;
    int mavalue;//区间的最大值

}node[3*maxn];
int score[maxn];
void buildtree(int left,int right,int u)
{
    node[u].left=left;
    node[u].right=right;
    if(left==right) node[u].mavalue=score[left];
    else
    {
        buildtree(left,(left+right)/2,2*u);
        buildtree(((left+right)/2)+1,right,2*u+1);
        node[u].mavalue=std::max(node[2*u].mavalue,node[2*u+1].mavalue);
    }
};
void updata(int stu,int val,int u)
{
    node[u].mavalue=std::max(val,node[u].mavalue);
    if(node[u].left==node[u].right) return;
    if(stu<=node[2*u].right)
        updata(stu,val,2*u);
    else updata(stu,val,2*u+1);
}
int query(int left,int right,int u)
{
    if(node[u].left==left&&node[u].right==right)
        return node[u].mavalue;
    if(right<=node[2*u].right)
        return query(left,right,2*u);
    if(left>=node[2*u+1].left)
        return query(left,right,2*u+1);
    int mid=(node[u].left+node[u].right)/2;
    return  std::max(query(left,mid,2*u),query(mid+1,right,2*u+1));
}
int main()
{
    int n,m;char temp;
    while(scanf("%d%c%d%c",&n,&temp,&m,&temp)!=EOF)
    {
        for(int i=0;i<n;i++)
            scanf("%d%c",&score[i],&temp);
        char c;int s,e;
        buildtree(1,n,1);
        for(int i=0;i<m;i++)
        {
            scanf("%c%c%d%c%d%c",&c,&temp,&s,&temp,&e,&temp);
            if(c=='U')
                updata(s,e,1);
            if(c=='Q')
                printf("%d\n",query(s,e,1));
        }
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值