zoj1610
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

大意是有一段区间最大8000,然后给N次染色操作,每次将一个[X,Y]的区间染为C色,N次操作完成以后,请问最后能看见的颜色有哪些,对每一种能看见的颜色,有几段区间是该颜色。
如例子:
0 4 4
0 3 1
3 4 2
0 2 2
0 2 3
最后[0,2]是颜色3,[2,3]是颜色1,[3,4]是颜色2,所以输出为:
1 1
2 1
3 1

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 8010
using namespace std;
int cl;
struct node{
    int left;
    int right;
    int color;//因为题中0也是color
    //所以 设-1 为无色  -2为混合色 
}a[4*N];
int sum[N];
//因为只是线段修改 所以不用建立l=r的结点 
void build(int l,int r,int p){
    a[p].left=l;
    a[p].right=r;
    a[p].color=-1;
    if(l==r-1) return ;
    build(l,(r+l)/2,2*p);
    build((r+l)/2,r,2*p+1);
}
void pushdown(int p){
    if(a[p].color>=0){
        a[2*p].color=a[p].color;
        a[2*p+1].color=a[p].color;
    }
    a[p].color=-2; //父节点设为混合色 
}
void pushup(int p){//如果左右颜色相等 父节点更新 
    if(a[2*p].color==a[2*p+1].color)
        a[p].color=a[2*p].color;
}
void update(int l,int r,int c,int p){
    if(a[p].left==l&&a[p].right==r){
        a[p].color=c;return ;
    }
    pushdown(p);
    int mid=(a[p].left+a[p].right)/2;
    if(r<=mid) update(l,r,c,2*p);
    else if(l>=mid) update(l,r,c,2*p+1);
    else {
        update(l,mid,c,2*p);
        update(mid,r,c,2*p+1);
    }
    pushup(p);
}
void query(int p){
    if(a[p].color>=0){//记录下上一个染的色与现在的比较
        if(a[p].color!=cl)//特殊判断连续同色的 如把2-3涂 1-3涂1  查询2-4时是一种颜色 
        {
            sum[a[p].color]++;
            cl=a[p].color;//更新连续颜色 
        }
        return ;
    }
    if(a[p].color==-2){ 
        query(2*p);
        query(2*p+1);
    }
    if(a[p].color==-1) cl=-1;
}
int main(){
    int n;
    build(0,N,1);
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<=N;i++)
            a[i].color=-1;
        memset(sum,0,sizeof(sum));
        while(n--){
            int c,x,y;
            scanf("%d%d%d",&x,&y,&c);
            update(x,y,c,1);
        }
        query(1);
        for(int i=0;i<=8000;i++){
            if(sum[i]==0) continue;
            else printf("%d %d\n",i,sum[i]);
        }
        printf("\n");
    }
    return 0;
}

poj 2777
Count Color
Time Limit: 1000MS

Memory Limit: 65536K
Total Submissions: 45540

Accepted: 13797
Description
Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.

There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, … L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board:

  1. “C A B C” Color the board from segment A to segment B with color C.
  2. “P A B” Output the number of different colors painted between segment A and segment B (including).

In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, … color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your.
Input
First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains “C A B C” or “P A B” (here A, B, C are integers, and A may be larger than B) as an operation defined previously.
Output
Ouput results of the output operation in order, each line contains a number.
Sample Input
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2
Sample Output
2
1
Source
POJ Monthly–2006.03.26,dodo

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100010
using namespace std;
int cl;
struct node{
    int left;
    int right;
    int color;
}a[4*N];
int sum[31];
int ans;
void build(int l,int r,int p){
    a[p].left=l;
    a[p].right=r;
    a[p].color=1;
    if(l==r) return ;
    build(l,(r+l)/2,2*p);
    build((r+l)/2+1,r,2*p+1);
}
void pushdown(int p){
    if(a[p].color>0){
        a[2*p].color=a[p].color;
        a[2*p+1].color=a[p].color;
    }
    a[p].color=-1;//-1 混合色 
}
void pushup(int p){
    if(a[2*p].color==a[2*p+1].color)
        a[p].color=a[2*p].color;
}
void update(int l,int r,int c,int p){
    if(a[p].left==l&&a[p].right==r){
        a[p].color=c;return ;
    }
    pushdown(p);
    int mid=(a[p].left+a[p].right)/2;
    if(r<=mid) update(l,r,c,2*p);
    else if(l>mid) update(l,r,c,2*p+1);
    else {
        update(l,mid,c,2*p);
        update(mid+1,r,c,2*p+1);
    }
    pushup(p);
}
void query(int l,int r,int p){
    if(a[p].color!=-1){//不是混合色就return return的唯一标准 
        sum[a[p].color]=1; return ;
    }
    int mid=(a[p].left+a[p].right)/2;
    if(r<=mid) query(l,r,2*p);
    else if(l>mid) query(l,r,2*p+1);
    else {//不用考虑a[p].left==l&&a[p].right==r的情况 因为 会在这里执行 
        query(l,mid,2*p);
        query(mid+1,r,2*p);
    }
}
int main(){
    int l,t,o;
    scanf("%d%d%d",&l,&t,&o);
    build(1,l,1);
    for(int i=1;i<=o;i++)
    {
        getchar();
        int x,y,c;
        char ch;
        scanf("%c",&ch);
        if(ch=='C')
        {
            scanf("%d%d%d",&x,&y,&c);
            if(x>y) swap(x,y);
            update(x,y,c,1);
        }
        else if(ch=='P')
        {
            memset(sum,0,sizeof(sum));
            scanf("%d%d",&x,&y);
            if(x>y) swap(x,y);
            ans=0;
            query(x,y,1);
            for(int i=1;i<=t;i++)
                if(sum[i]==1)ans++;
            printf("%d\n",ans);
        }
    }
    return 0;
}