Count the ColorsTime Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu
Description
Your task is counting the segments of different colors you can see at last.
Input
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
If some color can't be seen, you shouldn't print it.
Print a blank line after every dataset.
Sample Input
Sample Output
1 1
0 2
1 1
题意:对一段区间进行涂色,问最后每一种可见的颜色共占多少个不连续的区间。
方法:线段树+lazy标志
思路:这到题目的关键一点是区间不能取闭区间,根据题意,为了方便可以取左开右闭,而且要搞明白涂色的是区间而不是点,因此根据线段树不能一步得到结果,我们可以利用线段树的延时更新策略,即一个节点表示一段区间,如果这段区间是纯色的,那么会在这个点上进行标记,于是就不需要对其子区间进行图色了,除非下次图色的时候发生覆盖,才需要继续向下更新,最终线段树可以以较小的代价得到最终的色彩分布,然后,我们再去线性扫描一遍这个分布,就可以得到每种颜色的分布,将颜色值作为数组的下标,这样在扫描完成后得到的数据就是按照颜色值的变化的。
#include <iostream> #include <stdio.h> #include <string.h> #define maxn 8010 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; int color[maxn<<2]; int distrb[maxn];//颜色分布 int res[maxn]; void push_down(int rt) { if(color[rt]!=-1)//如果有延时更新标志 { color[rt<<1]=color[rt<<1|1]=color[rt];//更新子节点的标志 color[rt]=-1;//更新父节点的标志 } } void update(int L,int R,int data,int l,int r,int rt) { if(L<=l&&R>=r)//找到区间 { color[rt]=data; return; } if(color[rt]==data)//如果该区间包含该标记 return; push_down(rt);//向下更新 int m=(l+r)>>1; if(L<=m) update(L,R,data,lson); if(R>m) update(L,R,data,rson); } void query(int l,int r,int rt) { if(color[rt]!=-1)//该区间是纯色的 { for(int i=l; i<=r; i++) distrb[i]=color[rt];//将颜色的分布还原 return; } if(l!=r&&color[rt]==-1)//只有区间长度大于0才是有意义的 { int m=(l+r)>>1; query(lson); query(rson); } } int main() { int n,i; int left,right,data; int temp; while(~scanf("%d",&n)) { memset(color,-1,sizeof(color)); memset(distrb,-1,sizeof(distrb)); while(n--) { scanf("%d%d%d",&left,&right,&data); update(left+1,right,data,1,maxn,1);//区间是左开右闭的 } query(1,maxn,1);//查询整个区间 memset(res,0,sizeof(res)); for(i=0;i<maxn;)//遍历颜色分布,统计不同的色块 { while(i<maxn&&distrb[i]==-1) i++; if(i>=maxn) break; temp=distrb[i]; res[temp]++; while(i<maxn&&distrb[i]==temp) i++; } for(i=0;i<maxn;i++)//输出 { if(res[i]!=0) printf("%d %d\n",i,res[i]); } printf("\n"); } return 0; }