POJ 2777-Count Color(線段樹-區間染色查詢)

kewlgrl發表於2017-04-14
Count Color
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 45268   Accepted: 13705

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


題目意思:

L長的木板染上T種顏色,有O個操作,其中C a b c表示a~b長度區間全部染成c這種顏色,Q a b表示查詢區間a~b內不同顏色的個數。

解題思路:

線段樹節點儲存該區間內的顏色,單點區間肯定就是染成的顏色,大區間如果標記為-1則表示該區間由多種顏色的小區間組成,注意初始情況下木板均為同一種顏色,可以記為1。
一共有最多30種顏色,所以用bool vis[30]陣列標記,在每次查詢的時候清空,查詢到點或區間顏色相同時,對該顏色標記為true,最後統計1~T這T種顏色使用的個數即vis是true的情況。

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define INF 0xfffffff
#define MAXN 275000
bool vis[50];//1表示該區間有該顏色
int ans[MAXN*4];
struct Node //樹
{
    int l,r;//左右節點
    int col;//區間內的顏色
};
Node tree[MAXN*5];

void BuildTree(int root, int l, int r)//建樹
{
    tree[root].l=l;
    tree[root].r=r;
    tree[root].col=1;//初始狀態都是同一種顏色
    if(l!=r)
    {
        BuildTree(2*root,l,(l+r)/2);
        BuildTree(2*root+1,(l+r)/2+1,r);
    }
}
void Insert(int i,int l,int r,int c)//插入
{
    if(tree[i].col==c)//同色
        return ;
    if(tree[i].l==l&&tree[i].r==r)
    {
        tree[i].col=c;//染色
        return ;
    }
    if(tree[i].col!=-1)//同色
    {
        tree[2*i].col=tree[2*i+1].col=tree[i].col;
        tree[i].col=-1;
    }
    int mid=(tree[i].l+tree[i].r)/2;
    if(r<=mid)
        Insert(2*i,l,r,c);
    else if(l>mid)
        Insert(2*i+1,l,r,c);
    else
    {
        Insert(2*i,l,mid,c);
        Insert(2*i+1,mid+1,r,c);
    }
}
void Query(int i,int l,int r)
{
    if(tree[i].col!=-1)//同色
    {
        vis[tree[i].col]=true;
        return;
    }
    int mid=(tree[i].l+tree[i].r)/2;
    if(r<=mid)
        Query(2*i,l,r);
    else if(l>mid)
        Query(2*i+1,l,r);
    else
    {
        Query(2*i,l,mid);
        Query(2*i+1,mid+1,r);
    }
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("G:/cbx/read.txt","r",stdin);
    //freopen("G:/cbx/out.txt","w",stdout);
#endif
    int l,t,n;
    scanf("%d%d%d\n",&l,&t,&n);
    //while(~scanf("%d%d%d\n",&l,&t,&n))
    {
        BuildTree(1,1,n);//建樹
        while(n--)
        {
            char ch;
            cin>>ch;
            if(ch=='C')
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                if(a>b) swap(a,b);//如果a>b
                Insert(1,a,b,c);
            }
            else if(ch=='P')
            {
                memset(vis,false,sizeof(vis));
                int a,b,ans=0;
                scanf("%d%d",&a,&b);
                if(a>b) swap(a,b);
                Query(1,a,b);
                for(int i=1; i<=t; ++i)
                    if(vis[i]) ++ans;
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}


相關文章