【题意】给了每一线段的颜色,存在颜色覆盖,求表面上看能看到的颜色种类和各种颜色的段数
【分析&解题思路】延迟标记的思想,在儿子结点更新到之前,要把父亲节点的标记传到儿子结点。
【AC代码】
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 8005;
int vis[maxn<<2],ans[maxn];
struct node{
int l,r,col;
}Tree[maxn<<2];
void Push_Down(int rt){
if(Tree[rt].col!=-1){
Tree[rt<<1].col=Tree[rt<<1|1].col=Tree[rt].col;
Tree[rt].col=-1;
}
}
void Build(int l,int r,int rt){
Tree[rt].l=l,Tree[rt].r=r,Tree[rt].col=-1;
if(l==r) return ;
int mid=(l+r)>>1;
Build(l,mid,rt<<1);
Build(mid+1,r,rt<<1|1);
}
void Update(int L,int R,int c,int rt){
if(L<=Tree[rt].l&&Tree[rt].r<=R){
Tree[rt].col=c;
return ;
}
else{
Push_Down(rt);
int mid=(Tree[rt].l+Tree[rt].r)>>1;
if(L<=mid) Update(L,R,c,rt<<1);
if(mid<R) Update(L,R,c,rt<<1|1);
}
}
void query_ans(int rt){
if(Tree[rt].col>=0){
for(int i=Tree[rt].l; i<=Tree[rt].r; i++) vis[i]=Tree[rt].col;
return ;
}
if(Tree[rt].l==Tree[rt].r) return ;
if(Tree[rt].col!=-1) return ;
query_ans(rt<<1);
query_ans(rt<<1|1);
}
int main(){
int n,a,b,c;
while(~scanf("%d",&n)){
Build(1,maxn,1);
for(int i=0; i<n; i++){
scanf("%d%d%d",&a,&b,&c);
if(a>=b) continue;
Update(a+1,b,c,1);
}
memset(ans,0,sizeof(ans));
memset(vis,-1,sizeof(vis));
query_ans(1);
int i=1;
while(i<maxn){
int color=vis[i],j=i+1;
if(color==-1){i++;continue;}
while(vis[j]!=-1&&vis[j]==color&&j<maxn) j++;
++ans[color];
i=j;
}
for(int i=0; i<maxn; i++){
if(ans[i]){
printf("%d %d\n",i,ans[i]);
}
}
printf("\n");
}
return 0;
}