题目大意:给一个区间染色,区间为1到N,共有30种颜色可以挑选,初始时,区间全为第二种颜色。可以进行两种操作,一、给区间[a,b]染色成c;二、查询区间[a,b]有哪些颜色
分析:线段树成段替换。用lazy tag的思想。然后,就是存储颜色的时候,用二进制来存。题目给出30种颜色应该就是暗示要用二进制。
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson 2*root+1, l, m #define rson 2*root+2, m+1, r const int maxn = 1111111; int sum[4*maxn]; int add[4*maxn]; void Pushup(int root) { sum[root] = sum[2*root+1] | sum[2*root+2]; } void Pushdown(int root) { if(add[root]) { add[2*root+1] = add[2*root+2] = add[root]; sum[2*root+1] = add[root]; sum[2*root+2] = add[root]; add[root] = 0; } } void Build(int root, int l, int r) { add[root] = 0; if(l == r) { sum[root] = 1<<2; return; } int m = (l+r)>>1; Build(lson); Build(rson); Pushup(root); } void Update(int root, int l, int r, int L, int R, int c) { if(L <= l && r <= R) { add[root] = 1<<c; sum[root] = 1<<c; return; } Pushdown(root); int m = (l+r)>>1; if(L <= m) Update(lson, L, R, c); if(m < R) Update(rson, L, R, c); Pushup(root); } int Query(int root, int l, int r, int L, int R) { if(L <= l && r <= R) { return sum[root]; } Pushdown(root); int ret = 0; int m = (l+r)>>1; if(L <= m) ret |= Query(lson, L, R); if(m < R) ret |= Query(rson, L, R); return ret; } int main() { int n, m; char op[2]; int a, b, c; while(scanf("%d%d", &n, &m)) { if(n == 0 && m == 0) break; Build(0, 1, n); while(m--) { scanf("%s", op); if(op[0] == 'P') { scanf("%d%d%d", &a, &b, &c); Update(0, 1, n, a, b, c); } else { scanf("%d%d", &a, &b); int ans = Query(0, 1, n, a, b); int flag = 0; for(int i=1; i<=30; i++) { if(ans>>i & 1 && !flag) { printf("%d", i); flag = 1; } else if(ans>>i & 1) printf(" %d", i); } printf("\n"); } } } return 0; }