hdu1823 Luck and Love 二维线段树

    首先发表下做完后的感受:这题真他妈操蛋!!!大哭大哭一个简单的二维线段树,搞了一下午啊啊。。

思路:首先根据身高建一棵线段树,然后在每个节点上再以活泼度建一棵线段树,并记录每个区间的最大缘分值。

重点说细节了:在查询时可能会有A1>A2,H1>H2;然后就是插入数据时可能会有缘分值为0的数据,所以初始化时不要初始化为0;可能会插入身高和活泼度相同但缘分值不同的数据,因此还需要比较一下;最后一点,我写(int)(A*10)竟然会wrong,最后看了讨论改为(int)((A+eps)*10)就过了。

#include <iostream>
#include<cstdio>

using namespace std;
const double eps=1e-6;//看了讨论后加的。。。
struct subtree//活泼度
{
    int l, r;
    double MAXL;//最大缘分值
};

struct tree//身高
{
   int l, r;
   struct subtree node[4100];
}p[410];

void createnode(int i,int l,int r,int rt)
{
    p[i].node[rt].l=l;
    p[i].node[rt].r=r;
    p[i].node[rt].MAXL=-1.0;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    createnode(i,l,mid,rt<<1|1);
    createnode(i,mid+1,r,(rt<<1)+2);
}

void createtree(int l,int r,int rt)
{
    p[rt].l=l;
    p[rt].r=r;
    createnode(rt,0,1000,0);
    if(l==r)
        return;
    int mid=(l+r)>>1;
    createtree(l,mid,rt<<1|1);
    createtree(mid+1,r,(rt<<1)+2);
}

void insertnode(int i,int A,double L,int rt)
{
    if(p[i].node[rt].l==p[i].node[rt].r&&p[i].node[rt].l==A)
    {
        if(p[i].node[rt].MAXL<L)
            p[i].node[rt].MAXL=L;
        return;
    }
    int mid=(p[i].node[rt].l+p[i].node[rt].r)>>1;
    if(A<=mid)
        insertnode(i,A,L,rt<<1|1);
    else
        insertnode(i,A,L,(rt<<1)+2);
    p[i].node[rt].MAXL=max(p[i].node[rt<<1|1].MAXL,p[i].node[(rt<<1)+2].MAXL);
}


void insert(int H,int A,double L,int rt)
{
    insertnode(rt,A,L,0);//在包含该值的节点上都要插入
    if(p[rt].l==H&&p[rt].l==p[rt].r)
        return;
    int mid=(p[rt].l+p[rt].r)>>1;
    if(H<=mid)
        insert(H,A,L,rt<<1|1);
    else
        insert(H,A,L,(rt<<1)+2);
}

float querynode(int i,int A1,int A2,int rt)
{
    if(p[i].node[rt].l==A1&&p[i].node[rt].r==A2)
        return p[i].node[rt].MAXL;
    int mid=(p[i].node[rt].l+p[i].node[rt].r)>>1;
    if(A2<=mid)
        return querynode(i,A1,A2,rt<<1|1);
    else if(A1>mid)
        return querynode(i,A1,A2,(rt<<1)+2);
    else
        return max(querynode(i,A1,mid,rt<<1|1),querynode(i,mid+1,A2,(rt<<1)+2));
}

float query(int H1,int H2,int A1,int A2,int rt)
{
    if(p[rt].l==H1&&p[rt].r==H2)
        return querynode(rt,A1,A2,0);
    int mid=(p[rt].l+p[rt].r)>>1;
    if(H2<=mid)
        return query(H1,H2,A1,A2,rt<<1|1);
    else if(H1>mid)
        return query(H1,H2,A1,A2,(rt<<1)+2);
    else
        return max(query(H1,mid,A1,A2,rt<<1|1),query(mid+1,H2,A1,A2,(rt<<1)+2));
}

int main()
{
    int m,H1,H2;
    double A1,A2,L;
    char op[3];
    while(scanf("%d",&m),m)
    {
        createtree(0,100,0);
        while(m--)
        {
            scanf("%s",op);
            if(op[0]=='I')
            {
                scanf("%d%lf%lf",&H1,&A1,&L);
                H1-=100;//都统一减掉100,这样H的范围就是0-100
                insert(H1,int((A1+eps)*10),L,0);
            }
            else
            {
                scanf("%d%d%lf%lf",&H1,&H2,&A1,&A2);
                if(H1>H2)
                    swap(H1,H2);
                if(A1>A2)
                    swap(A1,A2);
                H1-=100;H2-=100;
                //不知道此处为何非要加上eps
                double ans=query(H1,H2,int((A1+eps)*10),int((A2+eps)*10),0);
                if(ans==-1.0)
                    printf("-1\n");
                else
                    printf("%.1lf\n",ans);
            }
        }
    }
    return 0;
}


 

 

 

你可能感兴趣的:(hdu1823 Luck and Love 二维线段树)