/*
ymc 2009/4/8 线段树
zju 1610
题目大意:
在x轴上,每次在某一个区间画一种颜色,求最后每种颜色的
选段要多少条。
l[i],r[i],c[i]表示在区间[l[i],r[i]]上画颜色c[i]
(颜色保存的时候保存c[i]+1,因为会出现0号颜色,但是
线段树中用0表示背景色)
用Left,Right记录最左边的左边和最右边的坐标
用Left_c,Right_c记录最小的颜色和最大的颜色
flag[i]记录第i号颜色的线段数。
*/
#include <iostream>
#include <limits>
using namespace std;
const int N=20000;
int tree[N];
int l[N],r[N],c[N];
int flag[N];
int n;
int Left,Right,Left_c,Right_c;;
void Init()
{
Left=INT_MAX;
Right=INT_MIN;
Left_c=INT_MAX;
Right_c=INT_MIN;
for(int i=0;i<n;i++)
{
scanf("%d %d %d",&l[i],&r[i],&c[i]);
if(l[i]<Left)
Left=l[i];
if(r[i]>Right)
Right=r[i];
c[i]++;
if(c[i]<Left_c)
Left_c=c[i];
if(c[i]>Right_c)
Right_c=c[i];
}
for(int k=1;k<=2*(Right-Left);k++)
tree[k]=0;//0为初始颜色即背景颜色
for(int k=Left_c;k<=Right_c;k++)
flag[k]=0;//所有颜色的线段数初始为0
}
/*
在以tree[k]为树根的线段树(代表的区间为[l,r])上
在区间[a,b]颜色c
*/
void Insert(int k,int l,int r,int a,int b,int c)
{
if(tree[k]==c)//已经有的颜色要要画的颜色相同
return;
if(l==a&&r==b)//正好画满整个线段树
{
tree[k]=c;
return;
}
if(tree[k]>=0)//[l,r]上已有一种颜色,则上色后有多种颜色
{
tree[2*k]=tree[k];
tree[2*k+1]=tree[k];
tree[k]=-1;//-1表示该区间有多种颜色
}
int m=(l+r)/2;
if(b<=m)//左儿子上色
Insert(2*k,l,m,a,b,c);
else if(m<=a)//右儿子上色
Insert(2*k+1,m,r,a,b,c);
else//左右儿子均上色
{
Insert(2*k,l,m,a,m,c);
Insert(2*k+1,m,r,m,b,c);
}
}
/*
在以tree[k]为树根的线段树[l,r]上统计不同颜色的线段数
lc,rc为[l,r]上左右端点的颜色
*/
void Count(int k,int l,int r,int &lc,int &rc)
{
if(tree[k]>=0)//[l,r]上颜色单一
{
lc=tree[k];//父节点需要知道
rc=tree[k];
flag[tree[k]]++;
return ;
}
if(l>=r) return;
int tl,tr;
Count(2*k,l,(l+r)/2,lc,tl);//统计左儿子
Count(2*k+1,(l+r)/2,r,tr,rc);//统计右儿子
if(tl==tr)//左儿子的最右线段与右儿子的最左线段同色
flag[tl]--;
}
void Solve()
{
for(int i=0;i<n;i++)
Insert(1,Left,Right,l[i],r[i],c[i]);
int lc,rc;
Count(1,Left,Right,lc,rc);
}
void OutPut()
{
for(int k=Left_c;k<=Right_c;k++)
if(flag[k]>0)
printf("%d %d\n",k-1,flag[k]);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
Init();
Solve();
OutPut();
printf("\n");
}
}