离散化:之前不知道怎么样离散化省时,因为一直超时;然后我用了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板块的数据支持和讨论!