@Acqua
2018-12-21T08:06:52.000000Z
字数 1372
阅读 1789
线段树
给定长度为的序列、种颜色,个操作,要求把内的所有数染成第种颜色,要求求出内颜色种数。
因为只有30种颜色,所以用二进制标记颜色。
线段树数组中存储以为根节点的树所维护的区间中颜色的二进制或 Or值。
更新不要顾头不顾尾。物理中有一种计算压强的方法,叫做液片法。写程序同理,要从更新过程中取一个断点,研究它的值的来源和目的地,借此构建递归方法。
// La Lune#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define N 100005#define root 1, 1, n#define lr u << 1#define rr u << 1 | 1#define lson lr, l, mid#define rson rr, mid + 1, r#define base int u, int l, int rusing namespace std;int t[N << 2], lz[N << 2];void build(base){t[u] = lz[u] = 0;if(l == r){t[u] = 1;return;}int mid = l + r >> 1;build(lson);build(rson);t[u] = t[lr] | t[rr];}void pushdown(int u){if(lz[u]){lz[lr] = lz[rr] = lz[u];t[lr] = t[rr] = t[u];lz[u] = 0;}}void update(base, int a, int b, int c){if(a <= l && r <= b){t[u] = lz[u] = (1 << (c - 1));return;}pushdown(u);int mid = l + r >> 1;if(a <= mid)update(lson, a, b, c);if(b > mid)update(rson, a, b, c);t[u] = t[lr] | t[rr];}int query(base, int a, int b){if(a <= l && r <= b)return t[u];pushdown(u);int mid = l + r >> 1;int res = 0;if(a <= mid)res |= query(lson, a, b);if(b > mid)res |= query(rson, a, b);return res;}int main(){int n, m, q;scanf("%d %d %d", &n, &m, &q);build(root);while(q--){char c;int x, y;scanf("\n%c %d %d", &c, &x, &y);if(x > y) swap(x, y);if(c == 'C'){int z;scanf(" %d", &z);update(root, x, y, z);}else if(c == 'P'){int res = query(root, x, y);int ans = 0;while(res > 0){ans += res & 1;res >>= 1;}printf("%d", ans);if(q > 0)printf("\n");}else printf("Error!\n");}return 0;}