poj2777

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 Output21

思路:填色,一开始完全没思路,看了下其他大佬的思路,因为颜色数量只有30可以用二进制来表示颜色,含有1代表有这种颜色,如101,代表有第一三种颜色,共两种。子区间可以通过‘|‘符号(或 的意思)来合并出上一级区间的状态如 101 | 110 = 111 .父区间含有三种颜色。因为查询操作较多,必须用线段树区间更新,主要是延迟标记,而且要用scanf输入.

实现代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;
const int M = 1e6+10;
int n,w,e;
int color[M<<2],lazy[M<<2];
void pushup(int rt){
   color[rt] = color[rt*2]|color[rt*2+1];
}

void build(int l,int r,int rt){
    if(l==r){
        color[rt] = 1;
        return ;
    }
    int m = (l+r)/2;
    build(l,m,rt*2);
    build(m+1,r,rt*2+1);
    pushup(rt);
}

void pushdown(int rt){
    if(lazy[rt]){
        lazy[rt*2] = (1<<(lazy[rt]-1));
        lazy[rt*2+1] = (1<<(lazy[rt]-1));
        color[rt*2] = color[rt];
        color[rt*2+1] = color[rt];
        lazy[rt] = 0;
    }
}

void update(int L,int R,int l,int r,int x,int rt){
     if(L<=l&&r<=R){
        lazy[rt] = x;
        color[rt] = (1<<(x-1));
        return ;
     }
     pushdown(rt);
     int m = (l+r)/2;
     if(L<=m)  update(L,R,l,m,x,rt*2);
     if(R>m) update(L,R,m+1,r,x,rt*2+1);
     pushup(rt);
}

int query(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R){
        return color[rt];
    }
    int ans1=0,ans2=0,ans;
    int m = (l+r)/2;
    pushdown(rt);
    if(L<=m) ans1+=query(L,R,l,m,rt*2);
    if(R>m)  ans2+=query(L,R,m+1,r,rt*2+1);
    ans = ans1|ans2;
    return ans;
}

void getsum(int x){
    int ans = 0;
    while(x){
        if(x%2==1) ans++;
        x/=2;
    }
    cout<<ans<<endl;
}

int main()
{
    int L,R,x;
    char c;
    while(scanf("%d%d%d",&n,&w,&e)!=EOF){
        memset(lazy,0,sizeof(lazy));
        build(1,n,1);
        while(e--){
        scanf("%c",&c);
        while(c==‘ ‘||c == ‘\n‘) scanf("%c",&c);
        if(c==‘C‘){
            scanf("%d%d%d",&L,&R,&x);
            if(L>R) swap(L,R);
            update(L,R,1,n,x,1);
        }
        else{
            scanf("%d%d",&L,&R);
            if(L>R) swap(L,R);
            int cnt = query(L,R,1,n,1);
            getsum(cnt);
        }
    }
    }
    return 0;
}
时间: 2024-10-12 06:47:29

poj2777的相关文章

poj2777 Count Color 2011-12-20

Count Color Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 23937Accepted: 7078 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

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>

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

POJ2777解题报告

题目地址: http://poj.org/problem?id=2777 题目概述: 给一块长度为L的板子,有两种操作,第一种将A到B刷成颜色C,第二种询问A到B一共有多少种颜色.颜色数小于等于30. 大致思路: 首先很容易发现线段树可以解决问题,不过怎么储存颜色呢?我们发现颜色总数很少,于是可以为2进制位来表示颜色,问题就可以很好地解决了. 代码: #include <iostream> #include <cstdio> #include <cstdlib> #in

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.

【POJ2777】Count Color(线段树)

以下是题目大意: 有水平方向上很多块板子拼成的墙,一开始每一块都被涂成了颜色1,有C和P两个操作,代表的意思是:C X Y Z —— 从X到Y将板子涂成颜色ZP X Y    —— 查询X到Y的板子共有多少种颜色 1 2 2 4 //有2块板子 两2颜色 4个询问 2 C 1 1 2 3 P 1 2 4 C 2 2 2 5 P 1 2 自己AC后上网查阅了许多别人的题解,看很多人用的什么“状态压缩”.“位运算”等等方法.感觉自己不会的知识还有很多.我用的方法是类似于hash的思想,每次将颜色查询

POJ2777线段树染色+lazy

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

poj2777( Count Color)

题目地址:Count Color 题目大意: 给一个划分为L的线段染色,有两种操作,一种C操作 给定l,r区间染色为val.另一种操作P 查询l,r区间的颜色有多少种. 解题报告: 线段树,区间更新. 这题的lazy 表示该区间颜色种类,如果单色则为“1”,如果多色为”0“.tag 代表该区间的哪一种颜色.如果修改区间的颜色时,判断修改的颜色和该区间的颜色是否相同,相同的话就return,如果直接找到该区间,直接lazy赋值为”1“,tag 赋值为”v“,不用往下递归,因为该区间包含下面的子区间

[日常摸鱼][poj2777]Count Color-线段树

辣鸡会考考完啦哈哈哈哈 题意:一块板分成$L$块,每次给一段连续的块染色或者询问一段有几种颜色,颜色的范围$\leq 30$ 我记得我好像做过一个类似的二维染色的问题-不过那个用树状数组直接过掉了- 这题颜色范围这么小的范围直接想到线段树了吧,直接把一个区间的颜色二进制按位压缩成一个状态,维护区间或 题面还特地说了可能$a>b$-然而我没看到 #include<cstdio> const int N=100005; inline int read() { int s=0,f=1;char