poj 2528

离散化:之前不知道怎么样离散化省时,因为一直超时;然后我用了map,果断又超,之前想到用O(n*n)的遍历方法来做,但想到铁定会超,就没有这样做了。

我的离散化是参考了网上的一部代码,其实核心是一样的,只是别人用了二维数组,而我用了结构体。首先,将开头和结尾存起来,但是在排序时是不分结尾和开始的,所以我们要先标记一下,也就是说将尾部用其数组的下标的负值来记录;然后用一个for循环搞定;(我最开始原始的想法是没有想到在原数组上修改,只是想到如何从原数组上映射到离散化后的标记,却没有想到可以逆向来做,直接可以修改其值。)

覆盖的处理:我之前的思想:举个例子;

假如有【1,10】之前有覆盖,然后接着是一组【2,7】,我是遇到这种情况,就将【1,1】和【8,10】重新插入一遍。。。。然后就是无止境的wa;(代码附于注释的代码)

我觉得原因在于:

剩下的我没有画出来,先解释一下:横的个数表示是次序,越少表示就是在前面;第二次的【1,10】会直接覆盖一个节点;而【1,5】也会保留,假如用我的那种方法的话,会出现在再次模拟插入的时候,将本应被覆盖的【1,5】也会被模拟插入。。。。然后就是不可想象的错误;

然后网上的思路就是:覆盖到哪里,就会将原来覆盖的标记退到其子节点。这样递归来处理;

#include<iostream>
#include<algorithm>
#include<map>
#include<cstring>
#define N 0xfffffff
using namespace std;
struct node
{
    int x1;
    int y1;
}s[11010];
struct node1
{
    int aa;
    int bb;
    int mark;
}w[21010<<2];
struct node3
{
    int ll;
    int sta;
}e[11000<<1];
int ss[21011];
int sum;
int cmp(node3 a1,node3 b1)
{
    return a1.ll<b1.ll;
}
void build(int l,int r,int nn)
{
    w[nn].aa=l;
    w[nn].bb=r;
    if(l==r)return ;
    int mid=(l+r)/2;
    build(l,mid,nn<<1);
    build(mid+1,r,(nn<<1)+1);
    return ;
}
void insert(int l,int r,int num,int nn)
{
    int mid=(w[nn].aa+w[nn].bb)/2;
    if(l==w[nn].aa&&r==w[nn].bb) w[nn].mark=num;
    else 
    {
        if(w[nn].mark>0)
        {
            w[nn<<1].mark=w[nn].mark;
            w[(nn<<1)+1].mark=w[nn].mark;
            w[nn].mark=-1;
            /*int uu=w[nn].mark;
            w[nn].mark=-1;
            if(w[nn].aa<l)
            insert(w[nn].aa,l,uu,nn);
            if(w[nn].bb>r)        
             insert(r,w[nn].bb,uu,nn);*/  //此处是我最开始的想法。再次插入
                }
                if(mid<l)
        {
            insert(l,r,num,(nn<<1)+1);
        }       
        else if(mid>=r)
        insert(l,r,num,(nn<<1));
        else 
        {
            insert(l,mid,num,nn<<1);
            insert(mid+1,r,num,(nn<<1)+1);
        }
    }
    return ;
}
void getsum(int nn)
{

    if(w[nn].mark>0)
    {
        if(!ss[w[nn].mark])
        {
           ss[w[nn].mark]=1;
           sum++;  
        }
        return ;
    }
        if(w[nn].aa==w[nn].bb)return ;
        getsum(nn<<1);
        getsum((nn<<1)+1);
    return ;
}//在整课树上寻找被标记的
int translate(int nn)
{
    int jj=1;
    int tmp=e[0].ll;
    int top=1;
    for(int ii=0;ii<nn;ii++)
    {
        if(tmp!=e[ii].ll)
        {
            tmp=e[ii].ll;
            top++;
        }
        if(e[ii].sta<0) s[-1*e[ii].sta].x1=top;
        else s[e[ii].sta].y1=top;
    }
    return top-1;
}//离散化(很佩服)
void init(int nn)
{
    
    for(int ii=0;ii<=nn;ii++)
    {
        ss[ii]=0;
        e[ii].ll=0;
        e[ii].sta=0;
    }
    memset(w,0,sizeof(w));
    return ;
}//初始化

int main()
{
    int i,j,m,n;
    int ma;
    scanf("%d",&n);
    while(n--)
    {
        sum=0;
        ma=-1*N;
        scanf("%d",&m);
        int l=0;
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&s[i].x1,&s[i].y1);
            e[l].sta=-1*i;
            e[l++].ll=s[i].x1;
            e[l].sta=i;
            e[l++].ll=s[i].y1;
        }
        sort(e,e+l,cmp);
        init(translate(l));
        build(1,20100,1);//建树
        for(i=1;i<=m;i++)
        {
            insert(s[i].x1,s[i].y1,i,1);
        }//插入
        getsum(1);
        printf("%d\n",sum);
    }
    return 0;
}
ps:多谢题目后discuss板块的数据支持和讨论!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值