hdu 5023 A Corrupt Mayor's Performance Art 广州网络赛 线段树的区间覆盖+种类查询

Problem Description

The wall was divided into N segments and the width of each segment was one cun(cun is a Chinese length unit). All segments were numbered from 1 to N, from left to right. There were 30 kinds of colors mayor X could use to paint the wall. They named those colors as color 1, color 2 .... color 30. The wall's original color was color 2. Every time mayor X would paint some consecutive segments with a certain kind of color, and he did this for many times. Trying to make his performance art fancy, mayor X declared that at any moment, if someone asked how many kind of colors were there on any consecutive segments, he could give the number immediately without counting.

Input
There are several test cases.

For each test case:

The first line contains two integers, N and M ,meaning that the wall is divided into N segments and there are M operations(0 < N <= 1,000,000; 0<M<=100,000)

Then M lines follow, each representing an operation. There are two kinds of operations, as described below:

1) P a b c
a, b and c are integers. This operation means that mayor X painted all segments from segment a to segment b with color c ( 0 < a<=b <= N, 0 < c <= 30).

2) Q a b
a and b are integers. This is a query operation. It means that someone asked that how many kinds of colors were there from segment a to segment b ( 0 < a<=b <= N).

Please note that the operations are given in time sequence.

The input ends with M = 0 and N = 0.
 

Output
For each query operation, print all kinds of color on the queried segments. For color 1, print 1, for color 2, print 2 ... etc. And this color sequence must be in ascending order.


要查询的是某个区间的颜色集合,用线段树维护子区间的颜色集合,用一个int型数据保存颜色的集合,1 << i 位是否为1表示第i种颜色是否存在

这场网络赛的所有题目的输出都没有后导空格。

//234MS	10584K
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define lch(x) ((x)<<1)
#define rch(x) ((x)<<1|1)

using namespace std;

const int MAX_N = int(1e6) + 1;
int sum[MAX_N<<2]; //tag[MAX_N<<2];
bool tag[MAX_N<<2];
char str[5];

inline void push_up(int n){
    sum[n] = sum[lch(n)] | sum[rch(n)];
}

inline void push_down(int n){
    if(tag[n]){
        //tag[lch(n)] = tag[rch(n)] = tag[n];
        tag[lch(n)] = tag[rch(n)] = true;
        sum[lch(n)] = sum[rch(n)] = sum[n];
        tag[n] = false;
    }
}

void build(int n, int l, int r){
    tag[n] = false;
    if(l == r){
        //scanf("%d", &sum[n]);
        sum[n] = 1<<2;
        return;
    }
    int mid = (l+r)>>1;
    build(lch(n), l, mid);
    build(rch(n), mid+1, r);
    push_up(n);
}

void modify(int a, int b, int v, int n, int l, int r){
    if(a <= l && r <= b){
        tag[n] = true;
        sum[n] = 1<<v;
        return;
    }
    push_down(n);
    int mid = (l+r)>>1;
    if(mid >= a) modify(a, b, v, lch(n), l, mid);
    if(mid+1 <= b) modify(a, b, v, rch(n), mid+1, r);
    push_up(n);
}

int query(int a, int b, int n, int l, int r){
    if(a <= l && r <= b) return sum[n];
    else{
        push_down(n);
        int mid = (l+r)>>1;
        if(b < mid+1) return query(a, b, lch(n), l, mid);
        else if(mid < a) return query(a, b, rch(n), mid+1, r);
        else return query(a, b, lch(n), l, mid) | query(a, b, rch(n), mid+1, r);
    }
}

int main(){
    int N, M;

    while(~scanf("%d%d", &N, &M)){
        if(N == 0 && M == 0) break;
        build(1, 1, N);

        int a, b, c;
        while(M--){
            scanf("%s", str);
            if(str[0] == 'P'){
                scanf("%d%d%d", &a, &b, &c);
                modify(a, b, c, 1, 1, N);
            }
            else if(str[0] == 'Q'){
                scanf("%d%d", &a, &b);
                int res = query(a, b, 1, 1, N);
                bool fir = false;
                for(int i=1; i<=30; i++){
                    if(res & (1<<i)){
                        if(fir) printf(" ");
                        printf("%d", i);
                        fir = true;
                    }
                }
                printf("\n");
            }
        }
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值