POJ 2777 Count Color (线段树的区间更新+lazy tag)

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

题解:

一开始搜了很多题解,说是要用进制来保存状态,一看这题最多有32种颜色,2的32次方。。数组早爆炸了,用多个数组有点麻烦,然后就找到了一个神犇的博客没用lazy tag写的,不是很熟哦线段树的我照着他的博客以我的方格打了一遍,把我的注释打了上去,原博客:http://www.2cto.com/kf/201512/454627.html

代码:

#include<stdio.h>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int MAX=1e5+5;
int vis[35];//颜色的访问数组
struct node
{
    int l,r;
    int color;//记录区间内的颜色,如果颜色为多种则为-1
}t[MAX*4];
int L,m,n;
void Build(int l,int r,int num)
{
    t[num].l=l;
    t[num].r=r;
    t[num].color=1;
    if(l==r)
        return;
    int mid=(l+r)/2;
    Build(l,mid,num*2);
    Build(mid+1,r,num*2+1);
}
void Getcolor(int l,int r,int num)//获得颜色种数
{
    if(t[num].color!=-1)//如果区间内颜色为一种,就把该颜色的vis置为1,不用往下搜索了
    {
        vis[t[num].color]=1;
        return;
    }
    int mid=(t[num].l+t[num].r)/2;//后面写法和一般的询问一样
    if(r<=mid)
        Getcolor(l,r,num*2);
    else if(l>mid)
        Getcolor(l,r,num*2+1);
    else
    {
        Getcolor(l,mid,num*2);
        Getcolor(mid+1,r,num*2+1);
    }
}
void update(int l,int r,int num,int c)//更新区间
{
    if(t[num].l==l&&t[num].r==r)//找到该区间,修改后返回
    {
        t[num].color=c;
        return;
    }
    if(t[num].color==c)//大区间和要修改的颜色一样则返回,不用往下修改了
        return;
    if(t[num].color!=-1)//lazy tag,如为同种颜色,更新子区间
    {
        t[num*2].color=t[num].color;
        t[num*2+1].color=t[num].color;
        t[num].color=-1;//将该区间标记为多种颜色
    }
    int mid=(t[num].l+t[num].r)/2;
    if(r<=mid)
        update(l,r,num*2,c);
    else if(l>mid)
        update(l,r,num*2+1,c);
    else
    {
        update(l,mid,num*2,c);
        update(mid+1,r,num*2+1,c);
    }
}
int main()
{
    int i,j,x,y,c;
    scanf("%d%d%d",&L,&m,&n);
    char ch;
    Build(1,L,1);
    for(i=1;i<=n;i++)
    {
        getchar();
        scanf("%c",&ch);
        if(ch=='C')
        {
            scanf("%d%d%d",&x,&y,&c);
            if(x>y)//保证区间从小到大
                swap(x,y);
            update(x,y,1,c);
        }
        else
        {
            scanf("%d%d",&x,&y);
            if(x>y)
                swap(x,y);
            memset(vis,0,sizeof(vis));
            Getcolor(x,y,1);
            int ans=0;
            for(j=1;j<=m;j++)
                if(vis[j])//找出区间内有几种颜色
                    ans++;
            printf("%d\n",ans);
        }
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值