POJ 2528 线段树+离散化~

中午1点到晚上7点,终于把你丫的做出来了!
开始是有思路的,半小时写完后用3分钟证明了自己的错误性。。。
于是重头再来。。第二遍写的时候在updata()里面绕了很久很久。。
最后写完提交发现MLE。。才发现这颗线段树这么大。。
在POJ上看评论提示说要用离散化。。于是无耻的去看了别人的代码。。
改进之后终于AC了。。。


题目大意:一块长度未知的宣传墙,N个人往上面贴海报,给定每个海报的起点与终点。求所有海报贴完后能被看到的海报数目。(被截断的两半算一张)


思路:用线段树可以解决,但是由于每个海报的起点与终点的取值范围是1e7,所以需要使用离散化。。


来来来:做个笔记撒~终于找到为何当初苦苦报错的原因了。。原来是因为cmp返回值原因导致端点从大到小排序。。从而最大的端点(一定是线段右端)先被离散化!又存进了节点的second属性。。导致second>first。。。。so。。。。
昨天改了cmp还AC让我想了好久。。。呜呜~~

#include<stdio.h>
#include<iostream>
#include<math.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define MAX_N 10005
#define MAX_I 20005
bool ID[MAX_N];
pair<int ,int> source[MAX_N];
struct P
{
    int fr;   //表示端点
    int li;    //表示所在的线
};
P point[MAX_N<<1];   //接收数据
bool cmp(const P a,const P b)   //重写sort方法
{
    return a.fr<b.fr;
}
int ans;
struct node
{
    int l;
    int r;
    int id;
}tree[MAX_I<<2];

void build(int l,int r,int dex)
{
    tree[dex].l=l;
    tree[dex].r=r;
    tree[dex].id=0;
    if(l==r) return;
    build(l,(l+r)/2,dex<<1);
    build((l+r)/2+1,r,(dex<<1)+1);
    return;
}
void updata(int l,int r,int dex,int id)
{

    if(l==tree[dex].l&&r==tree[dex].r)
    {
        tree[dex].id=id;
        return;
    }
    int m=(tree[dex].l+tree[dex].r)/2;
    if(m<l)
    {
        updata(l,r,(dex<<1)+1,id);
        //updata(tree[dex].l,l-1,dex,tree[dex].id);
        if(tree[dex].id!=0)
        {
            tree[dex<<1].id=tree[dex].id;
            if(m+1<l)
                updata(m+1,l-1,(dex<<1)+1,tree[dex].id);
            if(r+1<=tree[dex].r)
                updata(r+1,tree[dex].r,(dex<<1)+1,tree[dex].id);
            tree[dex].id=0;
        }


    }
    else if(r<=m)
    {
        updata(l,r,dex<<1,id);
        //updata(r+1,tree[dex].r,dex,tree[dex].id);
        if(tree[dex].id!=0)
        {
            tree[(dex<<1)+1].id=tree[dex].id;
            if(r<m)
                updata(r+1,m,dex<<1,tree[dex].id);
            if(l>tree[dex].l)
                updata(tree[dex].l,l-1,dex<<1,tree[dex].id);
            tree[dex].id=0;
        }

    }
    else
    {
        updata(l,m,dex<<1,id);
        updata(m+1,r,(dex<<1)+1,id);
        if(tree[dex].id!=0)
        {
            if(r+1<=tree[dex].r)
                updata(r+1,tree[dex].r,(dex<<1)+1,tree[dex].id);
            if(l>tree[dex].l)
                updata(tree[dex].l,l-1,dex<<1,tree[dex].id);
            tree[dex].id=0;
        }

    }
}
void query(int dex)
{
    if(tree[dex].id!=0)
    {
        if(ID[tree[dex].id]==0)
            ans++;
        ID[tree[dex].id]=1;
        return;
    }
    query(dex<<1);
    query((dex<<1)+1);

}
int main()
{
    int c,n,range,l,r;
    scanf("%d",&c);
    while(c--)
    {
        scanf("%d",&n);

        memset(ID,0,MAX_N);

       //数据离散化
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&l,&r);
            point[(i<<1)-1].fr=l;
            point[(i<<1)-1].li=i;
            point[i<<1].fr=r;
            point[i<<1].li=-i;
        }
        sort(point+1,point+n*2+1,cmp);
        int temp=point[1].fr;
        range=1;
        for(int i=1;i<=2*n;i++)
        {
            if(point[i].fr!=temp)
            {
                range++;
                temp=point[i].fr;
            }
            if(point[i].li<0)
                source[-point[i].li].second=range;
            else
                source[point[i].li].first=range;
        }
        //for(int i=1;i<=n;i++)
        //    printf("%d  %d\n",source[i].first,source[i].second);
        build(1,range,1);
        for(int i=1;i<=n;i++)
           updata(source[i].first,source[i].second,1,i);
        ID[0]=1;
        ans=0;
        query(1);
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值