HDU 1754 I Hate It

http://acm.hdu.edu.cn/showproblem.php?pid=1754

RMQ问题 树状数组和线段树都行

线段树专辑的题目相当多的代码是参考别人的,又左右引用,若原作者觉得和我的代码太过相似,我感到万分抱歉,希望谅解。

#include <iostream>
#include <cstring>
using namespace std;

const int MAX = 200010;
int N,M;

struct SegTree
{
    int left,right;        //左右端点
    int tag;            //当前线段下标
    int tot;            //标记数
    int nMax;            //区间最大值
}Tree[MAX*4];

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

void clear(int k)
{
    if(Tree[k].left + 1 != Tree[k].right)
    {
        Tree[2*k].tot = findmax(Tree[k].tot,Tree[2*k].tot);
        Tree[2*k+1].tot = findmax(Tree[k].tot,Tree[2*k+1].tot);
        Tree[k].nMax = findmax(Tree[k].nMax,Tree[k].tot);
        Tree[k].tot = 0;
    }
    else
    {
        Tree[k].nMax = findmax(Tree[k].nMax,Tree[k].tot);
        Tree[k].tot = 0;
    }
    return ;
}


//表示的区间为[l,r)
void buildTree(int l, int r, int k)
{
    Tree[k].left = l;
    Tree[k].right = r;
    Tree[k].tag = k;
    Tree[k].tot = 0;

    Tree[k].nMax = 0;

    if(l+1 == r)
        return ;

    //递归创建左右子树
    int mid = (l+r)>>1;
    buildTree(l,mid,2*k);
    buildTree(mid,r,2*k+1);
}

void modify(int l, int r, int k, int value)        //对区间[L,R)的修改
{
    if(l==Tree[k].left && Tree[k].right==r)
    {
        clear(k);
        Tree[k].tot = value;
        clear(k);
        return ;
    }

    int mid=(Tree[k].left+Tree[k].right)>>1;

    if(l<mid)
        modify(l,r,2*k,value);
    if(mid<r)
        modify(l,r,2*k+1,value);

    if(Tree[k].left +1 == Tree[k].right)
        return ;

    Tree[k].nMax = findmax(Tree[2*k].nMax,Tree[2*k+1].nMax);

    return ;
}

int query(int l, int r, int k)
{
    if(Tree[k].left == l && Tree[k].right == r)
        return Tree[k].nMax;

    clear(k);

    int mid = (Tree[k].left+Tree[k].right)>>1;

    if(r <= mid)
        return query(l,r,2*k);
    else if(l >= mid)
        return query(l,r,2*k+1);
    else
        return findmax(query(l,mid,2*k),query(mid,r,2*k+1));
}

int main()
{
    while(cin>>N>>M)
    {
        memset(Tree,0,sizeof(Tree));
        
        buildTree(1,N+1,1);        //构造[1,N+1)线段树

        for(int i=1; i<=N; i++)
        {
            int num;
            cin>>num;
            modify(i,i+1,1,num);
        }

        for(int i=1; i<=M; i++)
        {
            char ch;
            int a,b;
            cin>>ch>>a>>b;

            if(ch == 'Q')
                printf("%d\n",query(a,b+1,1));
            else
                modify(a,a+1,1,b);
        }
    }
    return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值