Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones.
Your task is counting the segments of different colors you can see at last.
Input
The first line of each data set contains exactly one integer n, 1 <= n <= 8000, equal to the number of colored segments.
Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:
x1 x2 c
x1 and x2 indicate the left endpoint and right endpoint of the segment, c indicates the color of the segment.
All the numbers are in the range [0, 8000], and they are all integers.
Input may contain several data set, process to the end of file.
Output
Each line输出的颜色索引应该包含一个颜色索引, 可以从顶部看到, 在此颜色的线段计数后, 他们应该根据颜色索引打印。
如果看不到某种颜色, 则不应打印。
Print a blank line after every dataset.
Sample Input
5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
4
0 1 1
3 4 1
1 3 2
1 3 1
6
0 1 0
1 2 1
2 3 1
1 2 0
2 3 0
1 2 1
Sample Output
1 1
2 1
3 1
1 1
0 2
1 1
/*
经典的线段树染色问题,成段更新懒标记。
这里考虑染色的片段,不是染色的结点。
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=8010;
struct node
{
int l,r;
int color;
}tree[maxn<<2];
int color[maxn]; //存储所有颜色片段个数,为0代表没有该颜色。
int temp;//用来存储上个颜色
void push_down(int k)//下传更新
{
tree[k<<1].color=tree[k<<1|1].color=tree[k].color;
tree[k].color=-2;//多种颜色
}
void build(int k,int l,int r)//建树
{
tree[k].l=l;
tree[k].r=r;
tree[k].color=-1;//代表没有颜色
if(l+1==r) return ;
int mid = (l+r)/2;
build(k<<1,l,mid);
build(k<<1|1,mid,r);
}
void insert(int k,int l,int r,int c)
{
if(l==r) return ;
if(tree[k].color==c) return ;
if(l<=tree[k].l&&r>=tree[k].r)
{
tree[k].color=c;
return ;
}
if(tree[k].color>=0) push_down(k);//存在颜色,下传更新
int mid=(tree[k].l+tree[k].r)/2;
if(r<=mid) insert(k<<1,l,r,c);
else if(l>=mid) insert(k<<1|1,l,r,c);
else{
insert(k<<1,l,mid,c);
insert(k<<1|1,mid,r,c);
}
tree[k].color=-2;
}
void count(int k)//统计颜色的段数
{
if(tree[k].color==-1)
{
temp=-1;
return ;
}
if(tree[k].color!=-2)//纯色
{
if(tree[k].color!=temp)//和上一个不同存入数组种
{
color[tree[k].color]++;
temp=tree[k].color;
}
return ;
}
if(tree[k].l+1!=tree[k].r)//递归求左儿子和右儿子
{
count(k<<1);
count(k<<1|1);
}
}
int main()
{
int n,a,b,c;
int Max;
while(scanf("%d",&n)!=EOF)
{
build(1,0,8000);
Max=0;
while(n--)
{
scanf("%d%d%d",&a,&b,&c);
insert(1,a,b,c);
if(c>Max)Max=c;
}//Max记录其中出现的最大颜色
temp=-1;//初始化为没有颜色
memset(color,0,sizeof(color));
count(1);
for(int i=0;i<=Max;i++)
if(color[i])
printf("%d %d\n",i,color[i]);
printf("\n");
}
return 0;
}