随笔 - 97, 文章 - 22, 评论 - 81, 引用 - 0
数据加载中……

HDU 1754 I Hate It

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754

/*
题意:
    给定一个长度为N(N <= 200000)的数列Si,紧接着Q(1 <= Q <= 5000)条询问
或者修改,询问是询问区间的最大值,修改是修改某一个位置的值。

解法:
线段树 或者 RMQ

思路:
    最裸的线段树区间最值,维护一颗完全二叉树,每个结点保存两个值,表示该结
点管理的区间的最大值和最小值,比如1号为根结点,管理区间[1, n],每个结点p有
左儿子2*p和右儿子2*p+1,当区间两端点相同时为叶子结点,如果p管理的是[a,b]那
么2*p则管理区间[a, (a+b)/2],2*p+1管理区间[(a+b)/2+1, b],如此一来就可以通
过递归,将儿子的信息传递给父亲,直至根节点。
*/



#include 
<iostream>

using namespace std;

#define inf -(1<<30)
#define maxn 200010

struct Tree {
    
int Max;
    
int son[2];
    
int l, r;

    
void clear() {
        son[
0= son[1= -1;
        Max 
= inf;
    }

    
void UpdateBy(Tree* ls, Tree* rs);
}
T[ maxn*4 ];

int root, tot;
int val[maxn];

int GetID(int& root) {
    
if(root == -1{
        root 
= tot++;
        T[root].clear();
    }

    
return root;
}

int mmax(int a, int b) {
    
return a > b ? a : b;
}


void Tree::UpdateBy(Tree* ls, Tree* rs){
    Max 
= mmax(ls->Max, rs->Max);
}


void Build(int& root, int l, int r) {
    GetID(root);
    T[root].l 
= l; T[root].r = r;
    
if(l == r) {
        T[root].Max 
= val[l];
        
return ;
    }

    
int mid = (l + r) >> 1;
    Build(T[root].son[
0], l, mid);
    Build(T[root].son[
1], mid+1, r);
    T[root].UpdateBy(
&T[T[root].son[0]], &T[T[root].son[1]]);
}


void Insert(int root, int pos, int val) {
    
if(pos > T[root].r || pos < T[root].l)
        
return ;
    
if(pos <= T[root].l && T[root].r <= pos) {
        
if(val > T[root].Max)
            T[root].Max 
= val;
        
return ;
    }

    Insert(T[root].son[
0], pos, val);
    Insert(T[root].son[
1], pos, val);

    T[root].UpdateBy(
&T[T[root].son[0]], &T[T[root].son[1]]);
}




int Query(int root, int l, int r) {
    
if(l > T[root].r || r < T[root].l)
        
return inf;
    
if(l <= T[root].l && T[root].r <= r) {
        
return T[root].Max;
    }

    
return mmax(Query(T[root].son[0], l, r), Query(T[root].son[1], l, r));
}


int n, m;
int main() {
    
int i;
    
while(scanf("%d %d"&n, &m) != EOF) {
        
for(i = 1; i <= n; i++{
            scanf(
"%d"&val[i]);
        }

        root 
= -1;
        tot 
= 0;
        Build(root, 
1, n);
        
        
while(m--{
            
char str[10];
            
int A, B;
            scanf(
"%s %d %d", str, &A, &B);
            
if(!strcmp(str, "U")) {
                Insert(root, A, B);
            }
else {
                printf(
"%d\n", Query(root, A, B));
            }

        }


    }

    
return 0;
}

posted on 2011-04-01 14:17 英雄哪里出来 阅读(1333) 评论(0)  编辑 收藏 引用 所属分类: 线段树


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理