题意:长为L的区间,初始每个单位区间都为颜色1,执行两种操作,C A B C,将区间[A, B]染为颜色C,P A B,询问区间A, B]有多少种颜色(1 <= L <= 100000, 1 <= 颜色T <= 30)。
题目链接:http://poj.org/problem?id=2777
——>>不错的题目,因为颜色的各类只有30种,所以每种颜色可以用1移位来表示,设col[o]表示线段树结点o的颜色状态,那么col[o]的低30位有多少个1就表示有多少种颜色。。。#^_^
#include <cstdio> #include <algorithm> using namespace std; #define lc (o<<1) #define rc ((o<<1)+1) const int maxn = (100000 + 10) << 2; bool one[maxn]; //是否为单一色 int col[maxn], sum; void build(int o, int l, int r) { col[o] = 1; //初始为颜色1 one[o] = true; //是单一色 if(l == r) return; int m = (l + r) >> 1; build(lc, l, m); build(rc, m+1, r); } void pushdown(int o) { col[lc] = col[rc] = col[o]; one[lc] = one[rc] = true; one[o] = false; } void update(int o, int l, int r, int ql, int qr, int v) { if(ql <= l && r <= qr) { col[o] = v; one[o] = true; return; } if(col[o] == v) return; if(one[o]) pushdown(o); int m = (l + r) >> 1; if(ql <= m) update(lc, l, m, ql, qr, v); if(qr > m) update(rc, m+1, r, ql, qr, v); col[o] = col[lc] | col[rc]; } void query(int o, int l, int r, int ql, int qr) { if((ql <= l && r <= qr) || one[o]) { sum |= col[o]; return; } int m = (l + r) >> 1; if(ql <= m) query(lc, l, m, ql, qr); if(qr > m) query(rc, m+1, r, ql, qr); } int solve() { int ret = 0; for(int i = 0; i < 30; i++) if((1<<i) & sum) ret++; return ret; } int main() { int L, T, O, A, B, C; char op; while(scanf("%d%d%d", &L, &T, &O) == 3) { build(1, 1, L); while(O--) { getchar(); op = getchar(); if(op == ‘C‘) { scanf("%d%d%d", &A, &B, &C); if(A > B) swap(A, B); update(1, 1, L, A, B, 1<<(C-1)); } else { sum = 0; scanf("%d%d", &A, &B); if(A > B) swap(A, B); query(1, 1, L, A, B); printf("%d\n", solve()); } } } return 0; }