POJ P2777 Count Color——线段树状态压缩

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.

          --by POJ

http://poj.org/problem?id=2777



题目大意:

区间染色,统计区间颜色数;

解法,线段树维护区间颜色情况,开桶;

因为颜色种类少,故压成二进制,应该快些;

挺水的题,代码也短;

代码如下:

#include<cstdio>
using namespace std;
const int MAXN=100010;
int tree[MAXN<<2];
int lz[MAXN<<2];
int n,t,o,L,R;
void up(int );
void down(int ,int ,int );
void col(int ,int ,int ,int );
int ask(int ,int ,int );
int ans(int );
int main()
{
    int i,j,k;
    char s[3];
    scanf("%d%d%d",&n,&t,&o);
    lz[1]=1;
    tree[1]=1;
    for(i=1;i<=o;i++){
        scanf("%s",s);
        if(s[0]==‘C‘){
            scanf("%d%d%d",&L,&R,&j);
            if(L>=R)
                k=L,L=R,R=k;
            col(1,n,1,j);
        }
        else{
            scanf("%d%d",&L,&R);
            if(L>=R)
                k=L,L=R,R=k;
            j=ask(1,n,1);
            printf("%d\n",ans(j));
        }
    }
}
void up(int nu){
    tree[nu]=tree[nu<<1]|tree[nu<<1|1];
}
void down(int l,int r,int nu){
    if(!lz[nu])return ;
    tree[nu<<1]=lz[nu];
    tree[nu<<1|1]=lz[nu];
    lz[nu<<1]=lz[nu<<1|1]=lz[nu];
    lz[nu]=0;
}
void col(int l,int r,int nu,int x){
    if(L<=l&&r<=R){
        tree[nu]=lz[nu]=(1<<(x-1));
        return ;
    }
    down(l,r,nu);
    int mid=(l+r)>>1;
    if(L<=mid)
        col(l,mid,nu<<1,x);
    if(R>mid)
        col(mid+1,r,nu<<1|1,x);
    up(nu);
}
int ask(int l,int r,int nu){
    if(L<=l&&r<=R)
        return tree[nu];
    down(l,r,nu);
    int ans=0,mid=(l+r)>>1;
    if(L<=mid)
        ans|=ask(l,mid,nu<<1);
    if(R>mid)
        ans|=ask(mid+1,r,nu<<1|1);
    return ans;
}
int ans(int x){
    int re=0;
    while(x){
        if(x&1)
            re++;
        x>>=1;
    }
    return re;
}

  

时间: 2024-10-07 06:47:20

POJ P2777 Count Color——线段树状态压缩的相关文章

POJ 2777 Count Color(线段树)

题目地址:POJ 2777 我去..延迟标记写错了.标记到了叶子节点上....这根本就没延迟嘛...怪不得一直TLE... 这题就是利用二进制来标记颜色的种类.然后利用或|这个符号来统计每个区间不同颜色种数. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h

POJ 2777 Count Color (线段树+位运算)

题意很简单了,对一个区间有两种操作: 1. "C A B C" Color the board from segment A to segment B with color C. //A~B涂上颜色C 2. "P A B" Output the number of different colors painted between segment A and segment B (including). //输出A~B间颜色的种类数 题目链接:http://poj.o

poj 2777 Count Color(线段树、状态压缩、位运算)

Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 38921   Accepted: 11696 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.

poj 2777 count color 线段树

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 d

POJ 2777 Count Color (线段树成段更新+二进制思维)

题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的颜色有几种. 很明显的线段树成段更新,但是查询却不好弄.经过提醒,发现颜色的种类最多不超过30种,所以我们用二进制的思维解决这个问题,颜色1可以用二进制的1表示,同理,颜色2用二进制的10表示,3用100,....假设有一个区间有颜色2和颜色3,那么区间的值为二进制的110(十进制为6).那我们就把

POJ 2777 count color(线段树,lazy标记)

这里有一个思想:我们在更新的时候不必要更新到叶子节点,只要更新到当前区间包含线段树区间即可. 设计一个标志位,更新到此. A Simple Problem with Integers 也是一个类似的题目 设计两个函数 push_down 将结点信息传递到下层节点(inc, sub,) push_up      将下层节点信息反馈到上层(max,min,count) #include <map> #include <set> #include <queue> #inclu

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

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>

POJ 2777 Count Color (线段树 + 状态压缩)

题目 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