zoj1610(线段树-染色区间连续段数…

来源:互联网 发布:java class 命名规范 编辑:程序博客网 时间:2024/06/06 11:03

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=610

ZOJ Problem Set - 1610
Count the Colors

Time Limit: 2 SecondsMemory Limit: 65536 KB

Painting some colored segments on a line, some previouslypainted segments may be covered by some the subsequent ones.

Your task is counting the segments of different colors you cansee at last.


Input

The first line of each data set contains exactly one integer n, 1<= n <= 8000, equal to the number ofcolored segments.

Each of the following n lines consists of exactly 3 nonnegativeintegers separated by single spaces:

x1 x2 c

x1 and x2 indicate the left endpoint and right endpoint of thesegment, c indicates the color of the segment.

All the numbers are in the range [0, 8000], and they are allintegers.

Input may contain several data set, process to the end offile.


Output

Each line of the output should contain a color index that can beseen from the top, following the count of the segments of thiscolor, they should be printed according to the color index.

If some color can't be seen, you shouldn't print it.

Print a blank line after every dataset.


Sample Input

5
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
4
0 1 1
3 4 1
1 3 2
1 3 1
6
0 1 0
1 2 1
2 3 1
1 2 0
2 3 0
1 2 1


Sample Output

1 1
2 1
3 1

1 1

0 2
1 1



Author: Standlove
Source: ZOJ Monthly, May 2003
#include
#include
#include
using namespace std;
#define maxn 8010
#define L(x) (x*2)
#define R(x) (x*2+1)
struct node
{
    int l;
    int r;
    intcol;
}node [maxn*3];
int cnt[maxn],pre;
void build(int t,int l,int r)
{
   node[t].l=l;
   node[t].r=r;
   node[t].col=-1;//初始化颜色为-1;
   if(l==r)
    {
       return ;
    }
    intmid=(l+r)/2;
   build(t*2,l,mid);
   build(t*2+1,mid+1,r);
}
void Update(int t,int l,int r,int col)//多种覆盖颜色为-2
{
   if(node[t].col==col)//颜色相同,返回
    {
       return;
    }
   if(l==node[t].l&&r==node[t].r)//全部重合才涂色
    {
       node[t].col=col;
       return;
    }
    //if( l<= segtree[n].left&& segtree[n].right<= r )
   //{               //大于改线段,更新颜色 ,所以不用担心下面的会越界
     //  segtree[n].kind = c;
      // return;
   //}
   if(node[t].col>=0&&node[t].l!=node[t].r)//如果不是混合色//存在颜色,做更新
    {
       //这个相当于是lazy标记pushdown
       //就是将lazy标记传递给子节点
       //延迟更新
       node[t*2].col=node[t].col;
       node[t*2+1].col=node[t].col;
    }
   node[t].col=-2;
    intmid=(node[t].l+node[t].r)/2;
   if(r<=mid)
    {
       Update(t*2,l,r,col);
    }
    elseif(l>=mid+1)
    {
       Update(t*2+1,l,r,col);
    }
    else
    {
       Update(t*2,l,mid,col);
       Update(t*2+1,mid+1,r,col);
    }
}
void Compute(int i) //计算线段树
{
   if(node[i].col>=0)//颜色不为-1和-2
    {
       if(node[i].col!=pre)
       {
           cnt[node[i].col]++;
       }
       pre=node[i].col;//更新前一个结点的颜色
       return;
    }
   if(node[i].col==-1)
    {
       pre=node[i].col;
       return;
    }
   Compute(i*2);
   Compute(i*2+1);
}
int main()
{
    intN,i,l,r,col;
   while(scanf("%d",&N)!=EOF)
    {
       build(1,1,8000);
       for(i=0;i
       {
           scanf("%d%d%d",&l,&r,&col);
           l++;//************
           Update(1,l,r,col);
       }
       pre=-1;
       memset(cnt,0,sizeof(cnt));
       Compute(1);
       for(i=0;i<=8000;i++)
       {
           if(cnt[i])
           {
               printf("%d %d\n",i,cnt[i]);
           }
       }
       printf("\n");
    }
    return0;
}
原创粉丝点击