查询某种颜色出现的段数,用线段树解。首次用线段树解该类题目。对于查询的时候,只不过需要注意,每次标记一下访问过的区间,它的颜色是不是和现在正在查询的区间的颜色视相同的,如果是则不比统计,因为它们是连续的一段,否则的话就要累加,然后记录该点的颜色。在递归的时候,总是先后查询相邻区间的颜色的值,故而采用此种方式能解决对应的线段的连续性问题。然后需要注意线段的最小区间长度是1,所以元线段为(l,l+1)。代码如下:
#include<stdio.h>
#include<string.h>
#define MAXN 8000
struct Node{
int l ;
int r ;
int color ;
}node[MAXN*4] ;
int n ;
int temp ;
int ncount[MAXN+5] ;
void build(int l , int r , int c){
node[c].l = l ;
node[c].r = r ;
node[c].color = -1 ;
if(l + 1 == r){
return ;
}
build(l , (l+r)/2 , c*2) ;
build((l+r)/2 , r , c*2+1) ;
}
void pushdown(int c){
if(node[c].color < 0){
return ;
}
node[c*2].color = node[c].color ;
node[c*2+1].color = node[c].color ;
node[c].color = -2 ;
}
void insert(int l , int r , int color , int c){
if(l==r)
return ;
if(node[c].color == color)
return ;
if(l == node[c].l && r == node[c].r ){
node[c].color = color ;
return ;
}
pushdown(c) ;
int mid = (node[c].l + node[c].r)/2 ;
if(mid >= r){
insert(l , r , color , c*2) ;
}
else if(mid<=l){
insert(l , r , color , c*2+1) ;
}
else {
insert(l , mid , color , c*2) ;
insert(mid , r , color , c*2+1) ;
}
}
void query(int c){
//区间为单一颜色
if(node[c].color >= 0 ){
if(node[c].color != temp){
ncount[node[c].color] ++ ;
temp = node[c].color ;
}
return ;
}
//区间长度不是元线段
if(node[c].l + 1 != node[c].r){
query(c*2) ;
query(c*2+1) ;
return ;
}
//区间未着色
else
temp = -1 ;
}
bool init(){
if(scanf("%d" , &n)==EOF){
return 0 ;
}
int i ;
int p ;
int q ;
int w ;
build(0 , 8000 , 1) ;
for(i = 0 ; i < n ; i ++){
scanf("%d %d %d" , &p ,&q ,&w) ;
insert(p , q , w , 1) ;
}
return 1 ;
}
void work(){
memset(ncount , 0 , sizeof(ncount)) ;
temp = -1 ;
query(1) ;
for(int i = 0 ; i < 8000 ; i ++){
if(ncount[i]){
printf("%d %d\n" , i , ncount[i]) ;
}
}
}
int main(){
while(init()){
work() ;
printf("\n") ;
}
return 0 ;
}