二维线段树解析 (HDU1823)解题报告

学习二维线段树,需有一维线段树的基础。倘若对一维线段树还不是很了解的同学可以点开这个链接看看。

http://blog.csdn.net/jobsandczj/article/details/47808213


Luck and Love

                                                                 Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                                                                              Total Submission(s): 5884    Accepted Submission(s): 1472


Problem Description
世界上上最远的距离不是相隔天涯海角
而是我在你面前
可你却不知道我爱你
                ―― 张小娴

前段日子,枫冰叶子给Wiskey做了个征婚启事,聘礼达到500万哦,天哪,可是天文数字了啊,不知多少MM蜂拥而至,顿时万人空巷,连扫地的大妈都来凑热闹来了。―_―|||
由于人数太多,Wiskey实在忙不过来,就把统计的事情全交给了枫冰叶子,自己跑回家休息去了。这可够枫冰叶子忙的了,他要处理的有两类事情,一是得接受MM的报名,二是要帮Wiskey查找符合要求的MM中缘分最高值。
 

Input
本题有多个测试数据,第一个数字M,表示接下来有连续的M个操作,当M=0时处理中止。
接下来是一个操作符C。
当操作符为‘I’时,表示有一个MM报名,后面接着一个整数,H表示身高,两个浮点数,A表示活泼度,L表示缘分值。 (100<=H<=200, 0.0<=A,L<=100.0)
当操作符为‘Q’时,后面接着四个浮点数,H1,H2表示身高区间,A1,A2表示活泼度区间,输出符合身高和活泼度要求的MM中的缘分最高值。 (100<=H1,H2<=200, 0.0<=A1,A2<=100.0)
所有输入的浮点数,均只有一位小数。
 

Output
对于每一次询问操作,在一行里面输出缘分最高值,保留一位小数。
对查找不到的询问,输出-1。
 

Sample Input
  
  
8 I 160 50.5 60.0 I 165 30.0 80.5 I 166 10.0 50.0 I 170 80.5 77.5 Q 150 166 10.0 60.0 Q 166 177 10.0 50.0 I 166 40.0 99.9 Q 166 177 10.0 50.0 0
 

Sample Output
  
  
80.5 50.0 99.9




#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
using namespace std;


double a[220][4040];
int n;
                                                        //H范围[0,200]
void build(int l,int r,  int id,int H)  //初始 rt==1  H==i;
{
    a[H][id] = 0;    //刚开始全部赋值为0 
    
    if(l == r)
{
 a[H][id] = 0;    
        return ;
}

    int m = (l + r) >> 1;   //除以2
     
    build(l,m,id<<1,H);
    build(m+1,r,(id<<1)+1,H);
}                                
                       //p->活泼度  q->缘分值  H->身高                    
void update(int l,int r,int p,double q,int id,int H)  //update(0,1000,(int)(aa*10),l,1,x);
                                                        //x->身高   aa->活泼度   l->缘分值
{
    if(l == r)
    {
      //H表示身高 
     a[H][id] = max(a[H][id],q); //q->缘分值  建树时a[][]里的值清零 
     
        return;
    }
    
    int m = (l + r) >> 1;
    
    if(p <= m)  //p->活泼度   活泼度与id有联系 
        update(l,m,p,q,id<<1,H);
        
    else
        update(m+1,r,p,q,(id<<1)+1,H);
        
    a[H][id] = max(a[H][id<<1],a[H][(id<<1)+1]);  //找到缘分值最大的 
}
                       //p-q表示活泼度要求范围  H->身高                                     
double query(int l,int r,int p,int q,int id,int H)  //query(0,1000,(int)(a1*10),(int)(a2*10),1,i);
{
    if(p <= l && q >= r)
    {
        return a[H][id];
    }
    
    int m = (l + r) >> 1;
    
    double ret = 0;
    
    if(p <= m)  //左半段 
    {
        ret = max(ret,query(l,m,p,q,id<<1,H));
    }
    
    if(q > m)  //右半段
    {
        ret = max(ret,query(m+1,r,p,q,(id<<1)+1,H));
    }
    return ret;
}




int main()
{

    int t,x,h,h1,h2,i;
    double aa,a1,a2,l;
    char str[10];
    while(scanf("%d",&t),t)
    {
        for(i = 0;i <= 200; i++)  //建树 
     build(0,1000,1,i);
     
        while(t--)
        {
        scanf("%s",str);
            if(str[0] == 'I')
            {
                scanf("%d %lf %lf",&x,&aa,&l);//x->身高   aa->活泼度   l->缘分值
    
                update(0,1000,(int)(aa*10),l,1,x);  //由于活泼度小数后最多一位,所以乘以10当做整数处理 
            }
            else
            {
                scanf("%d %d %lf %lf",&h1,&h2,&a1,&a2);
                
                if(h1 > h2)
                {
                swap(h1,h2);
                }
                if(a1 > a2)
                {
                swap(a1,a2);
                }
                
                
                double max = 0;
                
                for(i = h1;i <= h2; i++)   //身高范围用来遍历 
                {                             //a1,a2是活泼度    1表示结点id     
                double k = query(0,1000,(int)(a1*10),(int)(a2*10),1,i);
               
                if(max < k)
          max = k;
                }
                
                if(max == 0)
               printf("-1\n");
               
               else
               printf("%.1lf\n",max);
            }
        }
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值