HDU 1832:Luck and Love(二维线段树)

解题思路:

这个题目是一个二维线段树(属于树套树)的入门题,

一维每一行用来代表一个身高区域;

二维每一列用来代表一个或与都区域;

整个二维数组维护的是缘分值的最大值。

一维的线段树如果操作,二维的线段树也怎么操作。

每次就是线段树先考虑一维的,然后在考虑二维的。

题目给出的活跃度和缘分值都明确说明是一位小数,

因此我们将活跃度放大10倍,这样就可以维护整型

的区间。



AC代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>

#define lchild left,mid,root<<1
#define rchild mid+1,right,root<<1|1

using namespace std;

const int maxm = 210;  ///一维一个行代表身高区域
const int maxn = 1010; ///二维一个列代表活跃度区域
int a[maxm<<2][maxn<<2]; ///整个数组维护的是缘分值
int M;
void push_up(int row,int root)
{
    a[row][root] = max(a[row][root<<1],a[row][root<<1|1]);
}
void insert2(int row,int active,int love,int left,int right,int root)
{
    if(left == right)  ///到了叶子节点
    {
        ///这里注意,可能插入两条相同的记录,避免小值覆盖大值
        a[row][root] = max(a[row][root],love);
        return;
    }
    int mid = (left+right)>>1;
    ///递归插入左子树
    if(active<=mid) insert2(row,active,love,lchild);
    else insert2(row,active,love,rchild);
    ///递归插入右子树
    ///更新当前节点的最大值
    push_up(row,root);
}
void insert1(int height,int active,int love,int left,int right,int root)
{
    insert2(root,active,love,0,1000,1); 
    ///原来我把这句写在了left==right里面,后来发现第一条答案不对,才意识到这句应该在外边。
    if(left == right)
    {
        return;
    }
    int mid = (left+right)>>1;
    if(height<=mid) insert1(height,active,love,lchild);
    else insert1(height,active,love,rchild);
}
int query2(int row,int active1,int active2,int left,int right,int root)
{
    ///当前节点区间是要查询范围的子区间,返回节点值
    if(active1<=left && right<=active2)
    {
        return a[row][root];
    }
    int mid = (left+right)>>1;
    int ans = -1;
    ///递归查找子区间。
    if(active1 <= mid) ans = query2(row,active1,active2,lchild);
    if(active2 > mid) ans = max(ans,query2(row,active1,active2,rchild));
    return ans;
}
int query1(int height1,int height2,int active1,int active2,int left,int right,int root)
{
    if(height1<=left && right<=height2)
    {
        return query2(root,active1,active2,0,1000,1);
    }
    int mid = (left + right)>>1;
    int ans = -1;
    if(height1 <= mid) ans = query1(height1,height2,active1,active2,lchild);
    if(height2 > mid) ans = max(ans,query1(height1,height2,active1,active2,rchild));
    return ans;
}
int main()
{
    while(~scanf("%d",&M))
    {
        if(M == 0) break;
        char ch;
        ///直接将数组刷成-1.
        memset(a,-1,sizeof(a));
        for(int i = 1; i <= M; i++)
        {
            scanf(" %c",&ch);
            if(ch == 'I')  ///如果是I,插入一条记录
            {
                int height;
                double Active;
                double Love;
                scanf("%d%lf%lf",&height,&Active,&Love);
                int A = (int)(Active*10);   ///把活跃度放大十倍,题目说了题中小数都是一位小数
                int L = (int)(Love*10);     ///把L也放大十倍,这里放不放大都行
                insert1(height,A,L,0,200,1);
            }
            else        ///如果是Q,查询相关记录
            {
                int height1,height2,temp;
                double active1,active2;
                scanf("%d%d%lf%lf",&height1,&height2,&active1,&active2);
                int A1 = (int)(active1*10);
                int A2 = (int)(active2*10);
                ///题目的小坑,输入的数据不一定从小到大。
                if(height1 > height2)
                {
                    temp = height1;
                    height1 = height2;
                    height2 = temp;
                }
                if(A1 > A2)
                {
                    temp = A1;
                    A1 = A2;
                    A2 = temp;
                }
                int ans = query1(height1,height2,A1,A2,0,200,1);
                if(ans == -1)
                    printf("-1\n");
                else
                    printf("%.1lf\n",ans*0.1);
            }
        }
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值