动态建线段树,hdu6183,参考杰少的博客

我的代码不知为什么t掉了,这个等杰少回来再去问问他

先把我t掉的代码放在这里,主要是学一下动态建树的思想

这个是非常省空间的

这题目主要思路就是对每个颜色建一颗线段树,保存其y1,y2,范围内的点到y轴的最小距离

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 0x3f3f3f3f


using namespace std;

struct Tree
{
    int l,r,val;
};

Tree tree[4001000];
int cnt,Root[56];

void update(int&root,int val,int poi,int l,int r)
{
    if (root==-1)
    {root=cnt;cnt++;}
    if (l==r)
    {tree[root].val=min(val,tree[root].val);tree[root].l=tree[root].r=-1;return;}

    int mid=(l+r)/2;
    if (poi<=mid)
    {
        update(tree[root].l,val,poi,l,mid);
        if (tree[root].r==-1)
            tree[root].val=tree[tree[root].l].val;
        else
            tree[root].val=min(tree[tree[root].l].val,tree[tree[root].r].val);
    }
    else
    {
        update(tree[root].r,val,poi,mid+1,r);
        if (tree[root].l==-1)
            tree[root].val=tree[tree[root].r].val;
        else
            tree[root].val=min(tree[tree[root].l].val,tree[tree[root].r].val);
    }
    return;
}

int query(int root,int ql,int qr,int l,int r)
{
    if (root==-1) return inf;
    if (ql>r||qr<l) return inf;

    if (ql<=l&&qr>=r)
        return tree[root].val;


    int mid=(l+r)/2;
    return min(query(tree[root].r,ql,qr,mid+1,r),query(tree[root].l,ql,qr,l,mid));
}

void init()
{
    cnt=1;
    memset(Root,-1,sizeof(Root));
    for (int k=0 ;k<4000100;k++)
        {tree[k].l=tree[k].r=-1;tree[k].val=inf;}
    return;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if (n==0)
        {
            init();
        }
        else if (n==1)
        {
            int x,y,c;
            scanf("%d %d %d",&x,&y,&c);
            update(Root[c],x,y,1,1000000);
        }
        else if (n==2)
        {
            int x,y1,y2;
            scanf("%d %d %d",&x,&y1,&y2);
            if (y1>y2)
                {y1^=y2;y2^=y1;y1^=y2;}
            int cou(0);
            for (int k=0;k<=50;k++)
            {
                if (query(Root[k],y1,y2,1,1000000)<=x)
                  {cou++;}
            }
            printf("%d\n",cou);
        }
        else return 0;
    }
    return 0;
}

在杰少的帮助下终于过了,原来是我的线段树写的丑了点

最怕卡常数的题目

现在附上ac代码,两个代码只有query函数不同

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define inf 0x3f3f3f3f


using namespace std;

struct Tree
{
    int l,r,val;
};

Tree tree[4001000];
int cnt,Root[56];

void update(int&root,int val,int poi,int l,int r)
{
    if (root==-1)
    {root=cnt;cnt++;}
    if (l==r)
    {tree[root].val=min(val,tree[root].val);tree[root].l=tree[root].r=-1;return;}

    int mid=(l+r)/2;
    if (poi<=mid)
    {
        update(tree[root].l,val,poi,l,mid);
        if (tree[root].r==-1)
            tree[root].val=tree[tree[root].l].val;
        else
            tree[root].val=min(tree[tree[root].l].val,tree[tree[root].r].val);
    }
    else
    {
        update(tree[root].r,val,poi,mid+1,r);
        if (tree[root].l==-1)
            tree[root].val=tree[tree[root].r].val;
        else
            tree[root].val=min(tree[tree[root].l].val,tree[tree[root].r].val);
    }
    return;
}

int query(int root,int ql,int qr,int l,int r)
{
    if (root==-1) return inf;
//    if (ql>r||qr<l) return inf;
//
//    if (ql<=l&&qr>=r)
//        return tree[root].val;
    if(l == ql && r == qr) return tree[root].val;


    int mid=(l+r)/2;
    if(qr <= mid) return query(tree[root].l,ql,qr,l,mid);
    else if(ql >= mid + 1) return query(tree[root].r,ql,qr,mid+1,r);
    return min(query(tree[root].l,ql,mid,l,mid), query(tree[root].r,mid + 1,qr,mid + 1,r));
}

void init()
{
    cnt=1;
    memset(Root,-1,sizeof(Root));
    for (int k=0 ;k<4000100;k++)
        {tree[k].l=tree[k].r=-1;tree[k].val=inf;}
    return;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if (n==0)
        {
            init();
        }
        else if (n==1)
        {
            int x,y,c;
            scanf("%d %d %d",&x,&y,&c);
            update(Root[c],x,y,1,1000000);
        }
        else if (n==2)
        {
            int x,y1,y2;
            scanf("%d %d %d",&x,&y1,&y2);
            if (y1>y2)
                {y1^=y2;y2^=y1;y1^=y2;}
            int cou(0);
            for (int k=0;k<=50;k++)
            {
                if (query(Root[k],y1,y2,1,1000000)<=x)
                  {cou++;}
            }
            printf("%d\n",cou);
        }
        else return 0;
    }
    return 0;
}


总结一下,如果要建多个线段树的话就开一个结构体,tree然后树上的每个节点都可以用这个结构体来存

然后对于第i个树,我们要找他的话就只要找到根节点就行了也就是root[i]

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值