天天看點

資料結構--線段樹--區間塗色問題

Count the Colors Time Limit: 2 Seconds       Memory Limit: 65536 KB Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones.

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

Input

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

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

Each line of the output should contain a color index that can be seen from the top, following the count of the segments of this color, 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

線段樹的典型應用

#include "cstdio"  //zju 1610  線段樹簡單應用
#include "cstring"
#include "iostream"
using namespace std;

#define N 8005
const int NoColor = -1; //無顔色标記
const int MulColor = -2; //混合色标記

struct node
{
    int l,r;
    int col;
}Tree[4*N];

int a[N],many[N]; //a[]用于記錄顔色,many[]統計顔色出現次數

void Build(int t,int l,int r)  //建樹
{
    Tree[t].l = l;
    Tree[t].r = r;
    Tree[t].col = NoColor;  //初始化全部變為無色
    if(Tree[t].l+1==Tree[t].r)  
        return ;
    int mid = (Tree[t].l + Tree[t].r)/2;
    Build(t<<1,l,mid);
    Build(t<<1|1,mid,r);
}

void Update(int t,int l,int r,int k)
{
    if(Tree[t].col == k)    //顔色相同,不用繼續考慮
        return ; 
    if(Tree[t].l==l && Tree[t].r==r)    //以目前節點為根節點的子樹全部線上段内,直接改變根節點顔色值,return ;
        {  Tree[t].col = k;    return ; }  
    if(Tree[t].l+1==Tree[t].r)  //到達最底層,更新線段顔色值,return ;
    {    Tree[t].col = k; return ; }
    if(Tree[t].col != MulColor)  //目前顔色值不為混合色,将顔色值向下推一層;
    {
        Tree[t<<1].col   = Tree[t].col;
        Tree[t<<1|1].col = Tree[t].col;
    }
    Tree[t].col = MulColor;  //節點顔色改變
    int mid = (Tree[t].l+Tree[t].r)/2;
    if(r<=mid)
        Update(t<<1,l,r,k);
    else if(l>=mid)
        Update(t<<1|1,l,r,k);
    else
    {
        Update(t<<1,l,mid,k);
        Update(t<<1|1,mid,r,k);
    }
}

void Stats(int t)   //統計每一節點的顔色狀态
{
    int i,j;
    if(Tree[t].l+1==Tree[t].r)
    {
        a[Tree[t].l] = Tree[t].col;
        return ;
    }
    if(Tree[t].col>=0)
    {
        for(i=Tree[t].l; i<Tree[t].r; ++i)
            a[i] = Tree[t].col;
        return ;
    }
    Stats(t<<1);
    Stats(t<<1|1);
}

int main()
{
    int n;
    int i,j;
    int x,y,k;
    while(scanf("%d",&n)!=-1)
    {
        Build(1,1,N); //建樹
        while(n--)
        {
            scanf("%d %d %d",&x,&y,&k);
            x++; y++;
            Update(1,x,y,k);  //加入新添加的線段,更新樹的顔色值
        }
        memset(a,0,sizeof(a));
        memset(many,0,sizeof(many));
        Stats(1);
        int t = -1;

        for(i=1; i<=8000; ++i)
        {
            if(a[i]==t) continue;
            t = a[i];
            if(t!=-1)
                many[t]++;
        }
        for(i=0; i<=8000; ++i)
        {
            if(many[i])
                printf("%d %d\n",i,many[i]);
        }
        printf("\n");
    }
    return 0;
}
           

繼續閱讀