POJ-2777Count Color 线段树+位移

这道题对于我这样的初学者还是有点难度的不过2遍A了还是很开心,下面说说想法……
Count Color
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 40302 Accepted: 12161

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
题目大意:
往画板上染色,画板长L(1<=L<=100000)颜色共有T种(1<=T<=30)给你O条操作(1<=O<=100000)操作分两种
(1)“C A B C”操作C:将【A,B】染成C色(开始时,画板都是颜色1)
(2)“P A B”操作P:【A,B】范围内颜色种数

(此题有个蛋疼的地方,读入的AB可能顺序颠倒...也是略坑)
这道题用位移来做,如果染成t种颜色,就把颜色左移t-1位,位移运算在这道题里完美展现,所以以后还是得注重这种表示方法,了解多了,自然做题顺畅
用二进制表示对应的区间涂了第几种颜色,这样每个区间除了延迟标记外,可以再开一个数组统计当前涂了哪几种颜色。这样就和一般的线段树一样了。
(这种思想值得学习)

最后再统计一下1的数目
下面是代码:

//这波位移非常的nice啊! 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxl 100001
int color[maxl<<2]={0},sum[maxl<<2]={0};

void updata(int now)
{
    sum[now]=sum[now<<1]|sum[now<<1|1]; 
}//or

void pushdown(int now)
{
        if (color[now]!=0)
            {
                color[now<<1]=color[now<<1|1]=color[now];
                sum[now<<1]=color[now];
                sum[now<<1|1]=color[now];
                color[now]=0;
            }
}

void build(int l,int r,int now)
{
    color[now]=1;
    if (l==r) return;
    int mid=(l+r)>>1;
    build(l,mid,now<<1);
    build(mid+1,r,now<<1|1);
    updata(now);
}

void change(int L,int R,int l,int r,int now,int newcolor)
{
    if (L<=l && R>=r)
        {
            color[now]=1<<(newcolor-1);
            sum[now]=color[now];
            return;

        }//位移表示颜色 
    int mid=(l+r)>>1;   
    pushdown(now);
    if (L<=mid)
        change(L,R,l,mid,now<<1,newcolor);
    if (R>mid)
        change(L,R,mid+1,r,now<<1|1,newcolor);
    updata(now);
}

int query(int L,int R,int l,int r,int now)
{
    if (L<=l && R>=r)
        return sum[now];
    pushdown(now);
    int mid=(l+r)>>1;
    int ans=0;
    if (L<=mid)
        ans=ans|query(L,R,l,mid,now<<1);
    if (R>mid)
        ans=ans|query(L,R,mid+1,r,now<<1|1);//要对结果取or 
    return ans;
}

int main()
{
    int l,t,o;
    while(~scanf("%d%d%d",&l,&t,&o))
        {
            build(1,l,1);
            for (int i=1; i<=o; i++)
                {
                    char command[2];
                    int left,right,data;
                    scanf("%s",&command);
                    if (command[0]=='C')
                        {
                            scanf("%d%d%d",&left,&right,&data);
                            if (left>right)
                                {
                                    int temp=left;
                                    left=right;
                                    right=temp;
                                }
                            change(left,right,1,l,1,data);
                        }
                    else
                        {
                            scanf("%d%d",&left,&right);
                            if (left>right)
                                {
                                    int temp=left;
                                    left=right;
                                    right=temp;
                                }
                            int ans=query(left,right,1,l,1);
                            int answer=0;
                            while (ans>0)
                                {
                                    if (ans & 1)
                                        answer++;
                                    ans=ans>>1;
                                }//这里表示颜色数 
                            printf("%d\n",answer);
                        }
                }
            printf("\n");
        }
    return 0;

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值