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.
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.
要查询的是某个区间的颜色集合,用线段树维护子区间的颜色集合,用一个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;
}