线段数-最大值-I Hate It(曾老代码)

来源:互联网 发布:js实现探探洗牌特效 编辑:程序博客网 时间:2024/05/28 16:09
/HDU1754-线段树模板(区间最大值):曾贵胜
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define N 200001
using namespace std;


int num[N];
struct Tree
{
    int l;    //左端点 
    int r;    //右端点 
    int Max;  //总数 
}tree[N*4];   //总线段长度为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].Max=num[l];      //赋初值 
   return;                     //递归出口 
    }
    int mid=(l+r)/2;
    build(root<<1,l,mid);           //root<<1 相当于root*2 ,即它的左孩子 
    build(root<<1|1,mid+1,r);       //root<<1|1 相当于root*2+1 ,即它的右孩子 
    tree[root].Max=max(tree[root<<1].Max,tree[root<<1|1].Max);  //父亲的Max=max(左孩子的Max,右孩子的Max)
}


void update(int root,int pos,int val)  //更新:root是根节点,pos和val表示将在pos点的值更新为val 
{
    if(tree[root].l==tree[root].r)     //如果是叶子节点,即是pos对应的位置 
    {
     tree[root].Max=val;            //更新操作 
   return;                        //递归出口 
    }
    int mid=(tree[root].l+tree[root].r)/2;
    if(pos<=mid)                              //如果pos点是root对应的左孩子 
        update(root<<1,pos,val);              //在左孩子里面找 
    else
        update(root<<1|1,pos,val);            //在右孩子里面找
    tree[root].Max=max(tree[root<<1].Max,tree[root<<1|1].Max);  //父亲的Max=max(左孩子的Max,右孩子的Max)
}

int query(int root,int L,int R)              //查询:root为根节点,[L,R]表示要查询的区间 
{
    if(L<=tree[root].l && R>=tree[root].r)   //如果要查询的区间[L,R]包含root节点表示的区间 
   return tree[root].Max;               //直接返回root节点的Max值 
    int mid=(tree[root].l+tree[root].r)/2;   
int ret1=0,ret2=0;
    if(L<=mid) ret1=query(root<<1,L,R);     //查询root节点的左孩子 
    if(R>mid)  ret2=query(root<<1|1,L,R);   //查询root节点的右孩子               
    return max(ret1,ret2);                  //返回左、右子树中较大值 
}


int main()
{
    freopen("hate.in","r",stdin);
    
    int n,m,a,b;
    char str[2];
    while(scanf("%d%d",&n,&m)!=EOF)
    {
for(int i=1;i<=n;i++) 
           scanf("%d",&num[i]);    //在学生i的成绩 
        build(1,1,n);              //从根节点1开始构建线段树,区间[1,n] 
        while(m--)
        {
        scanf("%s%d%d",str,&a,&b);
        if(str[0]=='Q')
        {
           if(a>b) swap(a,b);             //查询区间[a,b] 
           printf("%d\n",query(1,a,b));   //输出查询结果 
}
else  update(1,a,b);               //更新a点的值为b
        }
    }     
return 0;
}
0 0
原创粉丝点击