HDU 1754 I Hate It(线段树)

本文通过一道简单的线段树题目,对比了数组下标和指针实现方式的性能差异,并给出了详细的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题目比较简单裸线段树,注意在查询时根据已经查询出来的结果进行优化

其实写这个题目的目的是测试一下用数组下标写的线段树快,还是用指针

速度快,结果这个题目测试出来的结果一样,都是500ms,不知道这个算

是没测出结果还是说结果就是两者速度差不多!


数组下标:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define maxn 300050
#define Max(a,b) (a>b?a:b)
struct node
{
    int MAX;
    int L,R;
    int left,right;
}po[maxn*4];
int pos;
int ans;
int n,m,score[maxn];
int build_tree(int root)
{
    if(po[root].L == po[root].R)
    {
        po[root].MAX=score[po[root].L];
        return 0;
    }
    int mid=(po[root].L+po[root].R)>>1;
    po[root].left=pos;
    po[pos].L=po[root].L,po[pos].R=mid;
    pos++;
    build_tree(po[root].left);
    po[root].right=pos;
    po[pos].L=mid+1,po[pos].R=po[root].R;
    pos++;
    build_tree(po[root].right);
    po[root].MAX=Max(po[po[root].left].MAX,po[po[root].right].MAX);
    return 0;
}
int query(int root,int L,int R)
{
    if(po[root].MAX < ans)
    return 0;
    if(po[root].L==L && po[root].R==R)
    {
        if(ans <po[root].MAX)
        ans=po[root].MAX;
        return 0;
    }
    int mid=(po[root].L + po[root].R)>>1;
    if(R<=mid)
    query(po[root].left,L,R);
    else if(L > mid)
    query(po[root].right,L,R);
    else
   query(po[root].left,L,mid),query(po[root].right,mid+1,R);
   return 0;
}
int update(int root,int a,int b)
{
    if(po[root].L==po[root].R)//这里不用判断是否等于 a,肯定等于嘛
    {
        po[root].MAX=b;
        return 0;
    }
    int mid=(po[root].L+po[root].R)>>1;
    if(a<=mid)
    update(po[root].left,a,b);
    else
    update(po[root].right,a,b);
    po[root].MAX=Max(po[po[root].left].MAX,po[po[root].right].MAX);
    return 0;
}
int main()
{
    int i,j,k;
    char ch;
    int a,b;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        po[0].MAX=0;
        po[0].L=1,po[0].R=n;
        pos=1;
        ans=0;
        for(i=1;i<=n;i++)
        scanf("%d",&score[i]);
        build_tree(0);
        for(i=0;i<m;i++)
        {
            getchar();
            scanf("%c%d%d",&ch,&a,&b);
            if(ch=='Q')
            {
               query(0,a,b);
               printf("%d\n",ans);
                ans=0;
            }
            else
            {
                update(0,a,b);
            }
        }
    }
    return 0;
}


指针


#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define maxn 300050
#define Max(a,b) (a>b?a:b)
struct node
{
    int MAX;
    int L,R;
    node *left,*right;
}po[maxn*4];
int pos;
int ans;
int n,m,score[maxn];
int build_tree(node *root)
{
    if(root->L == root->R)
    {
        root->MAX=score[root->L];
        return 0;
    }
    int mid=(root->L+root->R)>>1;
    root->left=&po[pos];
    po[pos].L=root->L,po[pos].R=mid;
    pos++;
    build_tree(root->left);
    root->right=&po[pos];
    po[pos].L=mid+1,po[pos].R=root->R;
    pos++;
    build_tree(root->right);
    root->MAX=Max(root->left->MAX,root->right->MAX);
    return 0;
}
int query(node *root,int L,int R)
{
    if(root->MAX < ans)
    return 0;
    if(root->L==L && root->R==R)
    {
        if(ans <root->MAX)
        ans=root->MAX;
        return 0;
    }
    int mid=(root->L + root->R)>>1;
    if(R<=mid)
    query(root->left,L,R);
    else if(L > mid)
    query(root->right,L,R);
    else
   query(root->left,L,mid),query(root->right,mid+1,R);
   return 0;
}
int update(node *root,int a,int b)
{
    if(root->L==root->R)//这里不用判断是否等于 a,肯定等于嘛
    {
        root->MAX=b;
        return 0;
    }
    int mid=(root->L+root->R)>>1;
    if(a<=mid)
    update(root->left,a,b);
    else
    update(root->right,a,b);
    root->MAX=Max(root->left->MAX,root->right->MAX);
    return 0;
}
int main()
{
    int i,j,k;
    char ch;
    int a,b;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        po[0].MAX=0;
        po[0].L=1,po[0].R=n;
        pos=1;
        ans=0;
        for(i=1;i<=n;i++)
        scanf("%d",&score[i]);
        build_tree(&po[0]);
        for(i=0;i<m;i++)
        {
            getchar();
            scanf("%c%d%d",&ch,&a,&b);
            if(ch=='Q')
            {
               query(&po[0],a,b);
               printf("%d\n",ans);
                ans=0;
            }
            else
            {
                update(&po[0],a,b);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值