(精)1754 另一种方法实现线段树(这个里面没有用到value,但是添加了一个max)

来源:互联网 发布:mac imovie使用教程 编辑:程序博客网 时间:2024/06/01 09:54
/*1 线段树可以看做是一个很特别的二叉树2 如果说父亲节点是n,那么两个孩子节点分别是2*n和2*n+1.这样理解很不错*/#include <iostream>using namespace std;#define MAX 600000//#define MAX 100struct Node{    int l,r,mid,max;}node[MAX];//获取最大值int max(int a,int b){    return a>b?a:b;}//初始化(其中参数n代表第几层,所以在调用的时候都写上1)void inint(int a,int b,int n){    node[n].l=a;//左边    node[n].max=-1;//最大值,    node[n].r=b;//右边    node[n].mid=(a+b)/2;//中间值    //如果到倒数第二层返回    if(a+1==b)return; //建立左子树和右子树    inint(a,(a+b)/2,n*2);    inint((a+b)/2,b,2*n+1);}//更新(pos是学生id,value是学生的分数)(这个应该是从顶开始的,不是从低开始的)(n表示第几层)void update(int pos,int value,int n){//如果说要插入的值,大于原来节点的最大值,那么就更新原来的值(一路上所有的点都更新了)    if(value>node[n].max)node[n].max=value; //因为把这个线段树看做是左闭右开区间(所以这个条件代表达到最后一层,如果到达最后一层肯定返回)    if((node[n].l+1)==node[n].r)return;//放入左子树    if(pos<node[n].mid)    {        update(pos,value,2*n);    }//放入右子树    if(pos>=node[n].mid)    {        update(pos,value,2*n+1);    }}//把a到为b之间的最大值找出来。n是node 的层次的值,也就是说节点的id,也就是说,调用函数的时候n==1//同时也可以认为n就是key值,因为第一层是1,第二层是2,3,第三层是4,5,6,7int query(int a,int b,int n){//如果说已经到了需要查找的一层    if( node[n].l==a && node[n].r==b)return node[n].max;//如果说a<node[n].mid不一定表示在左区间//表示在做区间肯定有一部分在,所以应该分开计算,左区间到node[n].mid,还有就是从node[n].mid+1到b的部分    if(a<node[n].mid)    {//如果说完全在左区间        if(b<=node[n].mid)        {            return query(a,b,2*n);        }//如果左区间有一部分,右区间也有一部分        else        {            return max(query(a,node[n].mid,2*n),query(node[n].mid,b,2*n+1));//后面的2*n和2*n+1代表下一个数组的层次。        }    }//如果说右区间,就进入下一个二叉树的右子树    else    {        return query(a,b,2*n+1);    }}    int main(){//freopen("in.txt","r",stdin);    int n,m,t,a,b,i;    char ch;    while(cin >>n>>m)    {//初始化        inint(1,n+1,1);//输入n个学生的成绩        for(i=1;i<=n;i++)        {scanf("%d",&t);            update(i,t,1);        }            //开始查询        for(i=1;i<=m;i++)        {getchar();            cin >>ch;//输入a和b的(左右区间)            cin >>a>>b;//如果说是查询的话            if(ch=='Q')cout <<query(a,b+1,1)<<endl;//注意是b+1而不是b。因为线段树是一个左开右闭的的区间。//如果说是更新的话            elseupdate(a,b,1);        }    }    return 0;}