=====================================題目大意=====================================
在一條直線上給某些區間染色,染色時之前染的顏色會被覆蓋,輸出最後可以在直線上看見的顏色以及該顏色在直線上的區間個數。
=====================================算法分析=====================================
線段樹區間修改和延遲標記的簡單應用。
注意一下區間的插入,用整數X代表區間[X,X+1),那麼當輸入區間爲[A,B]時,插入線段樹的區間應當爲[A,B-1]。
查詢時,只需查詢到延遲標記便可記錄下當前節點代表的區間以及延遲標記的顏色。
查詢完後,將記錄的區間按照顏色從小到大(顏色相同時按照左端點從左到右)排序,然後掃描輸出答案。
=======================================代碼=======================================
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LSON(N) (N<<1)
#define RSON(N) (N<<1|1)
#define MID(L,R) (((L)+(R))>>1)
const int MAXN=8005;
int N,M,SegmTree[MAXN<<2],CntInter;
struct INTERVAL { int L,R,C; } Inter[MAXN];
bool cmp(INTERVAL I1,INTERVAL I2)
{
return (I1.C<I2.C)||(I1.C==I2.C&&I1.L<I2.L);
}
void Insert(INTERVAL& I,int L,int R,int N)
{
if(I.R<L||R<I.L)
{
return;
}
if(I.L<=L&&R<=I.R)
{
SegmTree[N]=I.C; return;
}
if(SegmTree[N]!=-1)
{
SegmTree[LSON(N)]=SegmTree[N];
SegmTree[RSON(N)]=SegmTree[N];
SegmTree[N]=-1;
}
int M=MID(L,R);
Insert(I,L,M,LSON(N));
Insert(I,M+1,R,RSON(N));
}
void Query(int L,int R,int N)
{
if(SegmTree[N]>=0)
{
Inter[CntInter].L=L;
Inter[CntInter].R=R;
Inter[CntInter].C=SegmTree[N];
++CntInter;
return;
}
if(L!=R)
{
int M=MID(L,R);
Query(L,M,LSON(N));
Query(M+1,R,RSON(N));
}
}
int main()
{
while(scanf("%d",&N)==1)
{
CntInter=0;
memset(SegmTree,-1,sizeof(SegmTree));
for(int i=0;i<N;++i)
{
scanf("%d%d%d",&Inter[i].L,&Inter[i].R,&Inter[i].C);
if(Inter[i].L<=--Inter[i].R)
{
Insert(Inter[i],0,MAXN,1);
}
}
Query(0,MAXN,1);
sort(Inter,Inter+CntInter,cmp);
for(int i=0;i<CntInter;++i)
{
int cnt;
for(cnt=1;i+1<CntInter;++i)
{
if(Inter[i].C!=Inter[i+1].C) { break; }
if(Inter[i].R+1!=Inter[i+1].L) { ++cnt; }
}
printf("%d %d\n",Inter[i].C,cnt);
}
printf("\n");
}
return 0;
}