hdu 1823 Luck and Love(二维线段树)

目测为了做这道题我可能写了近千行代码。

刚开始的时候看出来这道题应该是一个二维的线段树,我没有做过二维的线段树,就在脑子里yy二维的线段树应该是什么样子。我当时想的情况是先对第一个关键字进行建树,结束之后再在第一个树的每一个叶节点中对第二个关键字建树。废了好大劲儿终于把代码敲出来,然后提交TLE。

我想了一下,觉得这样的话查询效率会很低,对于第一个关键字的区间内的每一个值都要查询到叶节点,然后对于每一个叶节点又要重新进行一次查询,一直查询到符合条件的区间。我又想了想,觉得应该对于第一棵树中的每一个节点建树,这样查询效率会高很多。然后又是重新敲代码,代码完成后出现了不知名错误,测试数据一直越界。debugN久后无奈放弃。

最后我去看了下别人的代码是怎么建树的,发现他们都是将子树的数据存入一个结构体中,其他地方和我的思路都一样。然后我用这种方法开始建树。

结果还是很凄凉,代码敲完,先是出现了不知名的爆栈错误,找到是因为一个递归条件没有敲好。之后发现有一组测试数据通不过,检查了半天代码,发现是因为在更新时我只对叶节点的子树进行了更新操作。正确的操作应该是对每一个节点的子树进行更新操作。修改后测试数据终于通过,然后提交又发生了最让人纠结的RE。

当时心都快碎了,这个RE浪费了我好长时间。最后终于想到是给出的检查区间有可能a1>a2,b1>b2,这时候应该将两个值交换。OMG!

然后提交,不再RE,改WA了。FML!

这时候我已经在这道题上耽误了一天半的时间,我也没有心情再去重新纠结一个可能非常坑爹的bug了。我直接去看了discuss,结果这个bug倒真是我的错。题目中的测试数据有可能有两个条件相同的女孩儿,只有幸福值不同,在这样的情况下,这个线段树不应该像一般的线段树那样用新值去取代旧值,而是将两者比较,保留较大的那个。

再然后提交,NA。

#include<stdio.h>
#include<string.h>
struct sub_tree
{
    int l,r;
    int max;
};
struct node
{
    int x,y;
    sub_tree b[4100];
}a[800];
int Max(int x,int y)
{
    if(x>y)
        return x;
    else
        return y;
}
void Sub_CreatTree(int t,int tt,int l,int r)
{
    a[tt].b[t].l=l;
    a[tt].b[t].r=r;
    a[tt].b[t].max=-1;
    if(l==r)
        return ;
    int temp=t*2;
    int mid=(l+r)/2;
    Sub_CreatTree(temp,tt,l,mid);
    Sub_CreatTree(temp+1,tt,mid+1,r);
    return ;
}
void CreatTree(int t,int x,int y,int l,int r)
{
    a[t].x=x;
    a[t].y=y;
    Sub_CreatTree(1,t,l,r);
    if(x==y)
        return ;
    int temp=t*2;
    int mid=(x+y)/2;
    CreatTree(temp,x,mid,l,r);
    CreatTree(temp+1,mid+1,y,l,r);
    return ;
}
void Sub_InsertTree(int t,int tt,int y,int z)
{
    if(a[t].b[tt].l==a[t].b[tt].r)
    {
        if(a[t].b[tt].max<z)
			a[t].b[tt].max=z;
        return ;
    }
    int temp=tt*2;
    int mid=(a[t].b[tt].l+a[t].b[tt].r)/2;
    if(y<=mid)
        Sub_InsertTree(t,temp,y,z);
    else
        Sub_InsertTree(t,temp+1,y,z);
    a[t].b[tt].max=Max(a[t].b[temp].max,a[t].b[temp+1].max);
    return ;
}
void InsertTree(int t,int xx,int y,int z)
{
    Sub_InsertTree(t,1,y,z);
    if(a[t].x==a[t].y)
        return ;
    int temp=t*2;
    int mid=(a[t].x+a[t].y)/2;
    if(xx<=mid)
        InsertTree(temp,xx,y,z);
    else
        InsertTree(temp+1,xx,y,z);
    return ;
}
int Sub_FindTree(int t,int tt,int l,int r)
{
    int max=-1;
    if(a[t].b[tt].l==a[t].b[tt].r)
        return a[t].b[tt].max;
    int temp=tt*2;
    int mid=(a[t].b[tt].l+a[t].b[tt].r)/2;
    if(r<=mid)
        max=Max(max,Sub_FindTree(t,temp,l,r));
    else if(l>mid)
        max=Max(max,Sub_FindTree(t,temp+1,l,r));
    else
    {
        max=Max(max,Sub_FindTree(t,temp,l,mid));
        max=Max(max,Sub_FindTree(t,temp+1,mid+1,r));
    }
    return max;
}
int FindTree(int t,int x,int y,int l,int r)
{
    int max=-1;
    if(a[t].x==x&&a[t].y==y)
    {
        max=Max(max,Sub_FindTree(t,1,l,r));
        return max;
    }
    int temp=t*2;
    int mid=(a[t].x+a[t].y)/2;
    if(y<=mid)
        max=Max(max,FindTree(temp,x,y,l,r));
    else if(x>mid)
        max=Max(max,FindTree(temp+1,x,y,l,r));
    else
    {
        max=Max(max,FindTree(temp,x,mid,l,r));
        max=Max(max,FindTree(temp+1,mid+1,y,l,r));
    }
    return max;
}
int main()
{
    int T;
    while(scanf("%d",&T),T)
    {
        CreatTree(1,0,100,0,1000);
        getchar();
        while(T--)
        {
            char c;
            scanf("%c",&c);
            if(c=='I')
            {
                int x,y,z;
                double a,b;
                scanf("%d%lf%lf",&x,&a,&b);
					x-=100;
                getchar();
                y=(int)(a*10);
                z=(int)(b*10);
                InsertTree(1,x,y,z);
            }
            else if(c=='Q')
            {
                int x,y;
                double a,b;
                int l,r;
                scanf("%d%d%lf%lf",&x,&y,&a,&b);
					x-=100;
					y-=100;
                getchar();
                l=(int)(a*10);
                r=(int)(b*10);
				int temp;
				if(x>y)
				{
					temp=x;
					x=y;
					y=temp;
				}
				if(l>r)
				{
					temp=l;
					l=r;
					r=temp;
				}
                int max=-1;
                max=FindTree(1,x,y,l,r);
				/*
				double ans;
				ans=max*1.0;
				printf("%.1f\n",ans);
				*/
                if(max<0)
                    printf("-1\n");
                else
                {
                    double ans;
                    ans=max*1.0/10;
                    printf("%.1f\n",ans);
                }
            }
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值