这是经典的染色问题吧?!
第一次写离散化,第一次写线段树,写的时候挺迷茫,AC之后很兴奋...说一下这道题的小trick,大家如果仔细看一下这道题的discuss后会发现,我们在离散化的时候不能只考虑顺序相邻,还要考虑位置相邻,也就是说在顺序相邻而位置不相邻的两个坐标之间,我们要加一个虚拟点,保证离散化后的顺序相邻关系和位置相邻关系都和离散化之前相同。由于poj数据弱了,不考虑这个trick不影响AC,但也不像discuss里说的那样考虑这个trick就会wa.
另我用STL会TLE...貌似可以用hash表优化,这里优化的主要是空间了,并且可能会牺牲一点儿时间.
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 10005
struct Order{
int l,r;
};
bool IsExist[10000005],Hash[N];
int Map[10000005];
int Col[N<<4],Dis[N<<2],Cnt;
Order Act[N];
void Init()
{
memset(IsExist,0,sizeof(IsExist));
memset(Hash,0,sizeof(Hash));
memset(Map,0,sizeof(Map));
memset(Col,-1,sizeof(Col));
Cnt=0;
}
void PushDown(int rt)
{
Col[rt<<1]=Col[rt<<1|1]=Col[rt];
}
void Update(int L,int R,int l,int r,int rt,int col)
{
if(L<=l&&r<=R)
{
Col[rt]=col;
return ;
}
if(R<l||L>r)
return ;
if(Col[rt]!=-1)
{
PushDown(rt);
Col[rt]=-1;
}
int mid=(l+r)>>1;
Update(L,R,l,mid,rt<<1,col);
Update(L,R,mid+1,r,rt<<1|1,col);
if(Col[rt<<1]==Col[rt<<1|1]&&Col[rt<<1]!=-1)
Col[rt]=Col[rt<<1];
}
int Count(int l,int r,int rt)
{
if(Col[rt]!=-1)
{
if(!Hash[Col[rt]])
{
Hash[Col[rt]]=true;
return 1;
}
else
return 0;
}
int mid=(l+r)>>1;
if(l==r)
return 0;
else
return Count(l,mid,rt<<1)+Count(mid+1,r,rt<<1|1);
}
int main()
{
int c,n,l,r,i,j;
scanf("%d",&c);
while(c--)
{
scanf("%d",&n);
Init();
for(i=0;i<n;++i)
{
scanf("%d %d",&Act[i].l,&Act[i].r);
if(!IsExist[Act[i].l])
{
IsExist[Act[i].l]=true;
Dis[Cnt++]=Act[i].l;
}
if(!IsExist[Act[i].r])
{
IsExist[Act[i].r]=true;
Dis[Cnt++]=Act[i].r;
}
}
sort(Dis,Dis+Cnt);
Map[Dis[0]]=1;
for(i=1,j=2;i<Cnt;++i,++j)
{
if(Dis[i]-Dis[i-1]>1)
j++;
Map[Dis[i]]=j;
}
j--;
for(i=0;i<n;++i)
Update(Map[Act[i].l],Map[Act[i].r],1,j,1,i+1);
cout<<Count(1,j,1)<<endl;
}
return 0;
}