HDOJ-5023-A Corrupt Mayor's Performance Art 解题报告

       一道跟POJ2777线段树基本一样的题,不同点就在于输出时这道题是按照颜色id从小到大输出而不是输出颜色。简单讲一下题意:给围墙染色,P操作代表给坐标为[a,b]的墙染上id为c的颜色,而Q操作表示询问在[a,b]范围内的围墙颜色种类,并且按照升序输出颜色id。


       我的解题思路:肯定和POJ2777线段树一样,使用一个32位整型数来存储颜色(因为有30种颜色,所以不需要开一个长度为30的bool数组,事实上这样是导致TLE的关键)。使用按位或运算计算出范围颜色然后用一个整型数存储。最后写个函数顺序输出id就ok了。


       我的解题代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <ctime>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <map>

using namespace std;

#define N 1000000

struct tree     //定义线段树结构体
{
    int left;
    int right;
    int mid;
    int color;      //这个代表当前范围的颜色
    int set;        //延迟标记
    void init()
    {
        mid = (left + right) >> 1;
        color = 2;  //初始颜色为2
        set = 0;
        return;
    }
};

tree node[N<<2];
int ans;
int n, m;

void BuildTree(int left, int right, int x); //建立线段树

void P(int left, int right, int co, int x); //P操作

int Q(int left, int right, int x);          //Q操作

void PushUp(int x);     //向上更新

void PushDown(int x);   //向下更新

int main()
{
    char ch;
    int a, b, c;
    while (~scanf("%d %d", &n, &m))
    {
        if (n == m && m == 0) break;
        BuildTree(1, n, 1);
        while (m--)
        {
            scanf(" %c %d %d", &ch, &a, &b);
            if (ch == 'P')
            {
                scanf("%d", &c);
                P(a, b, c, 1);
            }
            else
            {
                ans = Q(a, b, 1);
                bool flag = false;      //为了使除了最后一个颜色后面输出换行其他都输出一个空格
                for (int i=1; i<=30; ++i)
                {
                    if ((ans & 1) == 1)
                    {
                        if (flag) putchar(' ');
                        printf("%d", i);
                        flag = true;
                    }
                    ans >>= 1;
                }
                putchar('\n');
            }
        }
    }
    return 0;
}

void BuildTree(int left, int right, int x)
{
    node[x].left = left;
    node[x].right = right;
    node[x].init();
    if (left == right) return;
    BuildTree(left, node[x].mid, x << 1);
    BuildTree(node[x].mid + 1, right, x << 1 | 1);
    return;
}

void P(int left, int right, int co, int x)
{
    if (node[x].left == left && node[x].right == right)
    {
        int num = 1;    //颜色id所转换的数
        for (int i=1; i<co; ++i) num <<= 1;     //将颜色id转换为颜色数
        node[x].set = num;
        node[x].color = num;    //这里注意=不要写成|=,就因为这地方错WA了好久...
        PushUp(x);
        return;
    }
    if (node[x].set != 0) PushDown(x);
    if (right <= node[x].mid)
    {
        P(left, right, co, x << 1);
    }
    else if (left > node[x].mid)
    {
        P(left, right, co, x << 1 | 1);
    }
    else
    {
        P(left, node[x].mid, co, x << 1);
        P(node[x].mid + 1, right, co, x << 1 | 1);
    }
    return;
}

void PushUp(int x)
{
    while (x != 1)
    {
        x >>= 1;
        node[x].color = node[x<<1].color | node[x<<1|1].color;
    }
    return;
}

void PushDown(int x)
{
    node[x<<1].color = node[x<<1|1].color = node[x].color;
    node[x<<1].set = node[x<<1|1].set = node[x].set;
    node[x].set = 0;
    return;
}

int Q(int left, int right, int x)
{
    if (node[x].left == left && node[x].right == right) 
    {
        return node[x].color;
    }
    if (node[x].set != 0) PushDown(x);
    if (right <= node[x].mid) 
    {
        return Q(left, right, x << 1);
    }
    if (left > node[x].mid)
    {
        return Q(left, right, x << 1 | 1);
    }
    return Q(left, node[x].mid, x << 1) | Q(node[x].mid + 1, right, x << 1 | 1);
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值