hdu 1754 线段树入门的题

来源:互联网 发布:java工程师要多少钱 编辑:程序博客网 时间:2024/04/27 18:32

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

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

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

#include<algorithm>#include<cstdio>#define maxn 200005struct 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 200005struct 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;}


原创粉丝点击