#5、6、7、9RE
#10 WA
调了好久都没改进——蒟蒻无奈
#include<bits/stdc++.h>
const int N=4e5+5;
#define lc (k<<1)
#define rc ((k<<1)|1)
#define mid ((l+r)>>1)
using namespace std;
inline int Read()
{
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return x*f;
}
struct Node
{
int l,r,h;
}P[N<<2];
struct Segment_Tree
{
int Maxn[N<<2];
void Pushdown(int k)
{
Maxn[lc]=max(Maxn[lc],Maxn[k]);
Maxn[rc]=max(Maxn[rc],Maxn[k]);
}
void Update(int k,int l,int r,int x,int y,int z)
{
//cout<<k<<' '<<l<<' '<<r<<' '<<x<<' '<<y<<' '<<z<<endl;
if(x<=l&&r<=y)
{
Maxn[k]=max(Maxn[k],z);
// cout<<'U'<<l<<' '<<r<<' '<<Maxn[k]<<endl;
return;
}
Pushdown(k);
if(x<=mid)
Update(lc,l,mid,x,y,z);
if(y>mid)
Update(rc,mid+1,r,x,y,z);
}
int Query(int k,int l,int r,int x)
{
//cout<<k<<' '<<l<<' '<<r<<' '<<x<<endl;
if(l==r)
return Maxn[k];
Pushdown(k);
if(x<=mid)
return Query(lc,l,mid,x);
else
return Query(rc,mid+1,r,x);
}
}St;
vector<int>V;
vector<pair<int,int> >Ans;
int main()
{
int n=Read();
for(int i=1;i<=n;i++)
{
P[i].h=Read(),P[i].l=Read(),P[i].r=Read();
V.push_back(P[i].l),V.push_back(P[i].r);
}
sort(V.begin(),V.end());
int m=unique(V.begin(),V.end())-V.begin();
for(int i=1;i<=n;i++)
{
P[i].l=lower_bound(V.begin(),V.end(),P[i].l)-V.begin()+1;
P[i].r=lower_bound(V.begin(),V.end(),P[i].r)-V.begin()+1;//离散化
St.Update(1,1,m,P[i].l,P[i].r-1,P[i].h); //区间修改
}
int tmp=0;
Ans.push_back(make_pair(V[0],0));
for(int i=1;i<m;i++)
{
int h=St.Query(1,1,m,i);//该点高度
if(h==tmp)//一马平川(这个点并没有使高度改变 )
Ans[Ans.size()-1].first=V[i];//推进(该高度的右端赋为下一点)
else//波澜起伏(该点为转折点——注意此时以记录该点(上个高度的)
{
Ans.push_back(make_pair(V[i-1],h));//找这个坐标当前高度的转折点
Ans.push_back(make_pair(V[i],h));//先标记当前高度的下一个点,慢慢标记右端点
}
tmp=h;//别忘了更新“上个高度”
}
Ans.push_back(make_pair(V[m-1],0));
printf("%d\n",Ans.size());
for(int i=0;i<Ans.size();i++)
printf("%d %d\n",Ans[i].first,Ans[i].second);
return 0;
}