zoj1610——Count the Colors

来源:互联网 发布:人族女捏脸数据 编辑:程序博客网 时间:2024/06/06 17:12

题目大意:给一个分成n段的木板涂色,后序涂色可能会覆盖之前的涂色,问最终露出来的颜色和他们的段数

输入:(可以有很多case)

            n(1 <= n <= 8000)

            第i次涂色的左端点 右端点  所涂的颜色序号(共n次涂色各占一行,所有数据的范围都是 [0, 8000])

输出:(每个case的输出中间有一个空行)

            最终漏出的颜色序号  涂了它的段数(按照颜色序号从小到大输出)

分析:线段树涂色问题。与poj2528类似,但是2528是点着色(一个数已经代表一小段了),这个是段着色(一个数就是一个端点)。要注意一点,不能用n来建树,而是用8000,也就是说其实树是固定的。

          更新时区间左值加1则与2528类似可以看成点来染色了,例如0 4 4就相当于染色1,2,3,4这四个段所以update(1,4,4)。update和down的部分都一样,与2528不同的是这个代码中的query将区间都压到了叶节点再进行统计,但是像2528那样做也可以(遇到单色区间就统计)。

代码:转载自http://blog.csdn.net/sin_xf/article/details/47726363

  1. #include<cstdio>  
  2. #include<cstring>  
  3. #include<algorithm>  
  4. #include<vector>  
  5. #include<map>  
  6. #include<set>  
  7. #define INF 0x3f3f3f3f  
  8. using namespace std;  
  9. typedef long long ll;  
  10. const int maxn = 1e4+5;  
  11. int col[maxn<<2];  
  12. int num[maxn];  
  13. int ncol;  
  14. void down(int l,int r,int rt){  
  15.     if(col[rt]!=-1){  
  16.         col[rt<<1]=col[rt<<1|1]=col[rt];  
  17.         col[rt]=-1;  
  18.     }  
  19. }  
  20. void update(int L,int R,int k,int l,int r,int rt){  
  21.     if(L<=l&&r<=R){  
  22.         col[rt]=k;  
  23.         return;  
  24.     }  
  25.     down(l,r,rt);  
  26.     int mid=(l+r)>>1;  
  27.     if(L<=mid) update(L,R,k,l,mid,rt<<1);  
  28.     if(R>mid) update(L,R,k,mid+1,r,rt<<1|1);  
  29. }  
  30. void query(int l,int r,int rt){  
  31.     if(l==r){  
  32.         if(col[rt]>=0&&col[rt]!=ncol) num[col[rt]]++; //统计连续颜色段的个数  
  33.         ncol=col[rt];//两个相邻区间颜色相同则不用统计成新的段数
  34.         return;  
  35.     }  
  36.     down(l,r,rt);  //将所有区间不是单色的都下压到叶子结点
  37.     int mid=(l+r)>>1;  
  38.     query(l,mid,rt<<1);  
  39.     query(mid+1,r,rt<<1|1);  
  40. }  
  41. int main()  
  42. {  
  43.     int n;  
  44.     while(scanf("%d",&n)!=-1){  
  45.         ncol=-1;  
  46.         memset(num,0,sizeof(num));  
  47.         memset(col,-1,sizeof(col));  //建树  
  48.         for(int i=1;i<=n;i++){  
  49.             int c,l,r;  
  50.             scanf("%d%d%d",&l,&r,&c);  
  51.             if(l<r) update(l+1,r,c,1,8000,1);  
  52.         }  
  53.         query(1,8000,1);  
  54.         for(int i=0;i<=8000;i++){  
  55.             if(num[i]) printf("%d %d\n",i,num[i]);  
  56.         }  
  57.         printf("\n");  
  58.     }  
  59. }

原创粉丝点击