题目描述
给出n个区间,一些区间被另一些区间包含,求出最大的层数。
输入:
第一行为整数n,接下来n行,每行两个整数x,y(0<=x<=y<=1000000),表示一个区间的左右端点。
输出:
输出一行只有一个整数,即最大层数。
样例输入:
6
2 10
6 9
1 2
7 8
1 8
8 10
样例输出:
3
平衡树的题目,就是这样的,没什么好说的,对于此题,不难想到将左端点排序,右端点依次加入到平衡树中(右端点在树中有序),然后统计其右儿子中可以达到的最大值就可以了。
但是我们考虑到有左端点或右端点相同的情况,所以排序时将左端点作为第一关键字(从小到大),把右端点作为第二关键字(从大到小)
然后维护一些域乱搞就行了……
#include <cstdio>
#include <iostream>
#include <algorithm>
#define MaxN 100010
using namespace std;
int n,ans;
struct line
{
int x,y;
inline void read()
{
scanf("%d%d",&x,&y);
}
}a[MaxN];
bool cmp(line a,line b)
{
if(a.x==b.x)
return a.y>b.y;
else return a.x<b.x;
}
struct SplayTree
{
#define setc(x,s,d) (c[p[s]=x][d]=s,update(x))
#define ch(x) (c[p[x]][1]==x)
int a[MaxN],c[MaxN][2],p[MaxN];
int f[MaxN],m[MaxN];
int rt,tot;
inline void update(int x)
{
m[x]=f[x];
for(int i=0;i<2;i++)
m[x]=max(m[x],m[c[x][i]]);
}
inline void SetRoot(int x)
{
a[rt=tot=1]=x;
c[1][0]=c[1][1]=0;
f[1]=m[1]=1;
}
inline void rotate(int x)
{
int f=p[x];
bool d=ch(x);
setc(f,c[x][!d],d);
if(p[f])
setc(p[f],x,ch(f));
else p[x]=p[f];
setc(x,f,!d);
}
inline void splay(int x)
{
while(p[x])
if(!p[p[x]])
rotate(x);
else if(ch(x)==ch(p[x]))
rotate(p[x]),rotate(x);
else rotate(x),rotate(x);
rt=x;
}
inline int find(int x)
{
int t=rt;
bool d;
for(;;)
{
if(x==a[t]) break;
if(c[t][d=(x>a[t])])
t=c[t][d];
else break;
}
return t;
}
inline int insert(int x)
{
int pos=find(x);
if(x==a[pos])
splay(pos),
f[pos]=max(f[pos]+1,m[c[pos][1]]+1),
update(pos);
else
{
a[++tot]=x;
setc(pos,tot,x>a[pos]);
splay(tot);
f[tot]=m[c[tot][1]]+1;
update(tot);
}
return m[rt];
}
}SP;
inline void init()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
a[i].read();
}
inline void work()
{
sort(a,a+n,cmp);
SP.SetRoot(a[0].y);
for(int i=1;i<n;i++)
ans=max(ans,SP.insert(a[i].y));
cout<<ans<<endl;
}
int main()
{
init();
work();
return 0;
}