hdu 1823

本文探讨了二维线段树在处理身高与活跃度区域交集最大值问题上的应用,通过构建子树与母树结构,实现高效查询与更新操作。

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

题目

二维的线段树。

把身高区域看成x轴,活跃度看成是y轴,就找所交区域内值的最大值。

把每一株线段树单独来看,很容易理解。

代码中有详细解释,代码如下:

#include<iostream>
#include<cstdio>
using namespace std;
#define maxn 2050

struct sub_Tree
{
    int l,r;
    int val;
};//子树

struct Tree
{
    int l,r;
    sub_Tree subtree[maxn<<2];
}tree[maxn<<2];//母树,其中的一个元素即为子线段树

void build_subTree(int l,int r,int sub_rt,int rt)
{
    tree[rt].subtree[sub_rt].l=l;
    tree[rt].subtree[sub_rt].r=r;
    tree[rt].subtree[sub_rt].val=-1;
    if(l==r) return ;

    int m=(l+r)>>1;
    build_subTree(l,m,sub_rt<<1,rt);
    build_subTree(m+1,r,sub_rt<<1|1,rt);
}//建立子树

void buildTree(int l,int r,int ll,int rr ,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    build_subTree(ll,rr,1,rt);
    if(l==r) return ;
    int m=(l+r)>>1;
    buildTree(l,m,ll,rr,rt<<1);
    buildTree(m+1,r,ll,rr,rt<<1|1);
}//建立母树

void update_subTree(int act,int lov,int sub_root,int rt)
{
    int l,r;
    l=tree[rt].subtree[sub_root].l;
    r=tree[rt].subtree[sub_root].r;
    if(l==r){
        tree[rt].subtree[sub_root].val=max(tree[rt].subtree[sub_root].val,lov);
        return ;
    }
    int m=(l+r)>>1;
    if(act<=m) update_subTree(act,lov,sub_root<<1,rt);
    else update_subTree(act,lov,sub_root<<1|1,rt);
    tree[rt].subtree[sub_root].val=max(tree[rt].subtree[sub_root<<1].val,tree[rt].subtree[sub_root<<1|1].val);
}//更新子线段树

void update(int act,int lov,int height,int rt)
{
    int l,r;
    l=tree[rt].l;
    r=tree[rt].r;
    update_subTree(act,lov,1,rt);
    if(l==r) return ;
    int m=(l+r)>>1;
    if(height<=m) update(act,lov,height,rt<<1);
    else update(act,lov,height,rt<<1|1);
}//更新母线段数

int query_subtree(int x,int y,int sub_root,int rt)
{
    int l,r;
    l=tree[rt].subtree[sub_root].l;
    r=tree[rt].subtree[sub_root].r;
    if(l==x&&r==y){
        return tree[rt].subtree[sub_root].val;
    }
    int m=(l+r)>>1;
    int ret=-1;
    if(x<=m) ret=max(ret,query_subtree(x,min(y,m),sub_root<<1,rt));
    if(y>m) ret=max(ret,query_subtree(max(m+1,x),y,sub_root<<1|1,rt));
    return ret;
}//询问子树

int query(int x,int y,int xx,int yy,int rt)
{
    int l,r;
    l=tree[rt].l;
    r=tree[rt].r;
    if(l==x&&r==y){
        return query_subtree(xx,yy,1,rt);
    }
    int m=(l+r)>>1;
    int ret=-1;
    if(x<=m) ret=max(ret,query(x,min(m,y),xx,yy,rt<<1));
    if(y>m) ret=max(ret,query(max(m+1,x),y,xx,yy,rt<<1|1));
    return ret;
}//询问母树

int main()
{
    int n;
    char op[5];
    while(scanf("%d",&n),n){
        buildTree(100,200,0,1000,1);
        while(n--){
            scanf("%s",op);
            int height1,height2;
            double act1,act2,lov;
            if(op[0]=='I'){
                scanf("%d%lf%lf",&height1,&act1,&lov);
       //         cout<<(int)(act1*10)<<" "<<(int)(lov*10)<<endl;
                update((int)(act1*10),(int)(lov*10),height1,1);
            }
            else{
                scanf("%d%d%lf%lf",&height1,&height2,&act1,&act2);
                if(height1>height2) swap(height1,height2);
                if(act1>act2) swap(act1,act2);
                double ans=query(height1,height2,(int)(act1*10),(int)(act2*10),1);
                if(ans<0) puts("-1");
                else printf("%.1lf\n",ans/10);
            }
        }
    }
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值