線段樹,要維護的是區間內含有的顏色種類。
在 push 、更新時,新增顏色到區間內;
在 pull 時,更新左右子樹的區間到自己的節點上。
每個節點使用位元運算紀錄顏色種類。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#pragma GCC optimize ("O3")
#pragma GCC target ("avx")
#define _DEBUG
//#include <bits/stdc++.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <functional>
#define MAXN 100010
#define MAXT 33
using namespace std;
const size_t TREENN=MAXN*3;
int seg[TREENN];
int lazy[TREENN];
inline void init(void) {
memset(seg, 0x00, sizeof(seg));
memset(lazy, 0x00, sizeof(lazy));
}
#ifdef DEBUG
inline void print_bit(int n) {
for (int i=MAXT; i>=0; --i) printf("%d", (n>>i)&1);
}
#endif
#define IN_RANGE (qL<=L && qR>=R)
#define OO_RANGE (L>qR || R<qL)
inline void _push(int lev, int seg[], int lazy[]) {
if (!lazy[lev]) return;
seg[lev<<1] = lazy[lev<<1] = lazy[lev];
seg[lev<<1|1] = lazy[(lev<<1)|1] = lazy[lev];
lazy[lev] = 0;
}
// 更新
inline void _pull(int lev, int seg[]) { seg[lev] = seg[lev<<1] | seg[(lev<<1)|1]; }
void update(int L, int R, int qL, int qR, int lev, int op, int seg[], int lazy[]) {
if (OO_RANGE) return;
int M = (L+R)>>1;
if (IN_RANGE) {
seg[lev] = op;
lazy[lev] = op;
return;
}
_push(lev, seg, lazy);
update(L, M, qL, qR, lev<<1, op, seg, lazy);
update(M+1, R, qL,qR, lev<<1|1,op,seg, lazy);
_pull(lev, seg);
}
int query(int L, int R, int qL, int qR, int flag, int seg[], int lazy[]) {
int M=(L+R)>>1;
if (OO_RANGE) return 0; // 沒東西
if (IN_RANGE) return seg[flag];
_push(flag, seg, lazy);
int left=0, right=0;
left = query(L,M,qL,qR,flag<<1,seg,lazy);
right = query(M+1,R,qL,qR,flag<<1|1,seg,lazy);
return left | right;
}
#define RL() fgets(temp, 4000, stdin)
#ifdef DEBUG
#define CHECK() \
for (int _NOTE=1; _NOTE<TREENN; ++_NOTE) { printf("%03d: ", _NOTE); print_bit(seg[_NOTE]); putchar(' '); print_bit(lazy[_NOTE]); putchar('\n'); }
#else
#define CHECK()
#endif
int main(void){
init();
char temp[128];
int L, T, O;
RL();
sscanf(temp,"%d%d%d", &L, &T, &O);
update(1, L, 1, L, 1, 2, seg, lazy);
CHECK();
for (int i=0; i<O; ++i) {
int a, b, c;
char op;
RL();
sscanf(temp, "%1c %d %d %d", &op, &a, &b, &c);
if (a>b) swap(a,b);
switch(op) {
case 'C':
update(1,L,a,b,1,1<<c, seg, lazy);
CHECK();
break;
case 'P':
int res = query(1, L, a, b, 1, seg, lazy)&(-2);
int sum = 0;
while(res) { sum += (res&1); res>>=1; }
CHECK();
printf("%d\n", sum);
break;
}
}
return 0;
}