您的位置:首页 > 其它

POJ 2777 Count Color(线段树+懒惰标记)

2017-08-14 20:35 330 查看

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:

“C A B C” Color the board from segment A to segment B with color C.

“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


题目大意

C A B C 代表将区间[A,B]染成颜色C,P A B 代表查询区间[A,B]有多少种颜色,初始状态下所有的节点颜色为1。

解题思路

类似于2558,只是在建树时将每一个节点的颜色初始化为1。

代码实现

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 100007
int color[maxn<<4];
bool vis[35];
int ans;
void build(int l,int r,int rt)
{
color[rt]=1;
if(l==r) return ;
int m=(l+r)/2;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
}
void PushDown(int rt)
{
color[rt<<1]=color[rt<<1|1]=color[rt];
color[rt]=-1;
}
void Update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
color[rt]=c;
return ;
}
//如果[L,R]与当前区间有交集,则将其标记下推,这样在查询时,只要遇到color[rt]!=-1,
//则其下面的区间全部为一种颜色,直接统计ans++就可以返回了
if(color[rt]!=-1) PushDown(rt);
int m=(l+r)/2;
if(m>=L) Update(L,R,c,l,m,rt<<1);
if(m<R) Update(L,R,c,m+1,r,rt<<1|1);
}
void Query(int L,int R,int l,int r,int rt)
{
if(color[rt]!=-1)
{
if(!vis[color[rt]])
{
ans++;
vis[color[rt]]=1;
}
return ;
}
if(l==r) return;
int m=(l+r)/2;
if(m>=L)
Query(L,R,l,m,rt<<1);
if(m<R)
Query(L,R,m+1,r,rt<<1|1);
}
int main()
{
int L,T,O;
char ch;
int s,e,c;
while(~scanf("%d %d %d%*c",&L,&T,&O))
{
build(1,L,1);
while(O--)
{
scanf("%c",&ch);
if(ch=='C')
{
scanf("%d %d %d%*c",&s,&e,&c);
if(s>e)
swap(s,e);
Update(s,e,c,1,L,1);
}
else
{
scanf("%d %d%*c",&s,&e);
if(s>e)
swap(s,e);
ans=0;
memset(vis,0,sizeof(vis));
Query(s,e,1,L,1);
printf("%d\n",ans);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: