POJ2777(线段树涂色问题)

Count Color

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 42828   Accepted: 12973

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

思路:因为只有30种颜色,所以可以用2进制数颜色。注意:l可能大于r
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN=100005;
typedef long long ll;
struct Node{
    ll color,lazy;
    int l,r;
}a[MAXN*3];
int n,m;
ll res;
void pushUp(int rt)
{
    a[rt].color=a[rt<<1].color | a[(rt<<1)|1].color;
}
void build(int rt,int l,int r)
{
    a[rt].l=l;
    a[rt].r=r;
    a[rt].lazy=0;
    if(l==r)
    {
        a[rt].lazy=1;
        a[rt].color=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build((rt<<1)|1,mid+1,r);
    pushUp(rt);
}
void pushDown(int rt)
{
    if(a[rt].lazy!=0)
    {
        a[rt<<1].lazy=a[rt<<1].color=a[rt].color;
        a[(rt<<1)|1].lazy=a[(rt<<1)|1].color=a[rt].color;
        a[rt].lazy=0;
    }
}
void update(int rt,int l,int r,int val)
{
    if(a[rt].l==l&&a[rt].r==r)
    {
        ll e=1;
        e<<=(val-1);
        a[rt].color=e;
        a[rt].lazy=e;
        return ;
    }
    pushDown(rt);
    int mid=(a[rt].l+a[rt].r)>>1;
    if(r<=mid)
    {
        update(rt<<1,l,r,val);
    }
    else if(mid<l)
    {
        update((rt<<1)|1,l,r,val);
    }
    else
    {
        update(rt<<1,l,mid,val);
        update((rt<<1)|1,mid+1,r,val);
    }
    pushUp(rt);
}
void query(int rt,int l,int r)
{
    if(a[rt].l==l&&a[rt].r==r)
    {
        res=res|a[rt].color;
        return ;
    }
    pushDown(rt);
    int mid=(a[rt].l+a[rt].r)>>1;
    if(r<=mid)
    {
        query(rt<<1,l,r);
    }
    else if(mid<l)
    {
        query((rt<<1)|1,l,r);
    }
    else
    {
        query(rt<<1,l,mid);
        query((rt<<1)|1,mid+1,r);
    }
}
int main()
{
    while(scanf("%d%*d%d",&n,&m)!=EOF)
    {
        build(1,1,n);
        for(int i=0;i<m;i++)
        {
            scanf("%*c");
            char op;
            int l,r;
            scanf("%c %d %d",&op,&l,&r);
            if(l>r)    swap(l,r);
            if(op==‘C‘)
            {
                int val;
                scanf("%d",&val);
                update(1,l,r,val);
            }
            else
            {
                res=0;
                query(1,l,r);
                int cnt=0;
                while(res>0)
                {
                    if(res&1)    cnt++;
                    res>>=1;
                }
                printf("%d\n",cnt);
            }
        }
    }
    return 0;
}
时间: 2024-09-30 16:10:39

POJ2777(线段树涂色问题)的相关文章

ZOJ1610( 经典线段树涂色问题)

#include"cstdio" #include"algorithm" #include"cstring" using namespace std; const int MAXN=8005; struct node{ int l,r; int flag; }a[MAXN*4]; void build(int rt,int l,int r) { a[rt].l=l; a[rt].r=r; a[rt].flag=-1; if(l==r) { ret

POJ2777 线段树区间染色问题

题意:给L长度的木板,给T种颜色,给O个操作,每次可以选择一段区间染色,或查询一个区间的颜色种类 思路:用线段树叶节点记录颜色所代表的数字,父节点为-1表示两个子节点颜色不相同,>0时的数字代表子节点全为这个数字对应颜色. #include <iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std

POJ2777线段树染色+lazy

第一次写这样的题目,反正出现了各种坑爹问题,调了老半天,除了延迟标记外,这题还要开一个cnt数组用来存储各个区间内颜色的种类数, 每次改变颜色时,更新一次. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #i

【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]

树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进行这几种操作: 1 x: 把点x到根节点的路径上所有的点染上一种没有用过的新颜色. 2 x y: 求x到y的路径的权值. 3 x: 在以x为根的子

[BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)

4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 692  Solved: 408[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进行这几种操作: 1 x: 把点x到根节点的路径上所有的点染上一种

BZOJ.4817.[SDOI2017]树点涂色(LCT DFS序 线段树)

题目链接 1.2裸树剖,但是3.每个点的答案val很不好维护.. 如果我们把同种颜色的点划分到同一连通块中,那么向根染色的过程就是Access()! 最初所有点间都是虚边,相同颜色点用实边相连.一条边由实边变为虚边时,深度大的点所在子树所有点val+1(Access()中原先x的右儿子答案+1,因为x颜色变了): 由虚边变为实边时,深度大的点所在子树所有点val-1(fa[x]颜色与x相同导致fa[x]的贡献没了).(其实是因为 实链数量(贡献)就等于虚边数量+1?无所谓了) 于是2.就是val

POJ2777 Count Color 线段树区间更新

题目描述: 长度为L个单位的画板,有T种不同的颜料,现要求按序做O个操作,操作分两种: 1."C A B C",即将A到B之间的区域涂上颜色C 2."P A B",查询[A,B]区域内出现的颜色种类 出现操作2时,请输出答案 PS:初始状态下画板颜色为1 一开始没有想那么好,用int整型位移来代替颜色,还是使用了最传统的bool color[来记录,可是不知道错在了哪里, #include<iostream> #include<cstdio>

[BZOJ]4817: [Sdoi2017]树点涂色

Time Limit: 10 Sec  Memory Limit: 128 MB Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进行这几种操作: 1 x: 把点x到根节点的路径上所有的点染上一种没有用过的新颜色. 2 x y: 求x到y的路径的权值. 3 x y: 在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大

poj2777(线段树)

题目链接:https://vjudge.net/problem/POJ-2777 题意:有L块连续的板子,每块板子最多染一种颜色,有T种(<=30)颜色,刚开始将所有板子染成颜色1,O次操作(包括将[a,b]染成颜色k,和询问[a,b]的不同颜色数),输出每次询问的值. 思路:典型的线段树的题目.用线段树实现表示一段区间的颜色值.线段树结点的属性包括l(区间左端点),r(区间右端点),value(区间的颜色值,1..T表示对应的颜色,0表示多种颜色),lazy(懒惰标记,如果不用lazy直接用v