5 10 P 1 2 3 P 2 3 4 Q 2 3 Q 1 3 P 3 5 4 P 1 2 7 Q 1 3 Q 3 4 P 5 5 8 Q 1 5 0 0
4 3 4 4 7 4 4 7 8
在片段上着色,有两种操作,如下:思路:
第一种:P a b c 把 a 片段至 b 片段的颜色都变为 c 。
第二种:Q a b 询问 a 片段至 b 片段有哪些颜色,把这些颜色按从小到大的编号输入,不要有重复
片段上默认的初始颜色为编号2的颜色。
1、利用线段树进行区间覆盖。
2、在每个节点上附上一个60大小的数组,便于将左右儿子的颜色编号合并到自己节点的数组上(因为颜色编号最多为30)。
3、每次合并左右儿子的颜色编号都需要一次排序和去重,防止记录数超过数组大小。
4、由于0 <N <= 1,000,000过大,可对所有的 a 和 b 做一次 hash ,减小建树的大小,防止爆内存。
/************************************************************************* > File Name: hdu5023.cpp > Author: Bslin > Mail: Baoshenglin1994@gmail.com > Created Time: 2014年09月20日 星期六 21时24分19秒 ************************************************************************/ #include <stdio.h> #include <algorithm> #include <string.h> using namespace std; const int N = 200010; const int M = 100010; struct node { int l, r; int cnt; bool flag; int num[70]; } tree[N << 2]; int ans[70], tot; int Hash[N], a[M], b[M], c[M]; char op[M]; void pushup(int p) { int i, cnt; memset(tree[p].num, 0, sizeof(tree[p].num)); for(i = 0; i < tree[p << 1].cnt; i ++) { tree[p].num[i] = tree[p << 1].num[i]; } int len = tree[p << 1].cnt; for(i = 0; i < tree[p << 1 | 1].cnt; i ++) { tree[p].num[len + i] = tree[p << 1 | 1].num[i]; } cnt = tree[p << 1].cnt + tree[p << 1 | 1].cnt; sort(tree[p].num, tree[p].num + cnt); tree[p].cnt = unique(tree[p].num, tree[p].num + cnt) - tree[p].num; } void pushdown(int p) { if(tree[p].flag) { tree[p << 1].flag = tree[p << 1 | 1].flag = 1; tree[p].flag = 0; memset(tree[p << 1].num, 0, sizeof(tree[p << 1].num)); memset(tree[p << 1 | 1].num, 0, sizeof(tree[p << 1 | 1].num)); tree[p << 1].cnt = 1; tree[p << 1 | 1].cnt = 1; tree[p << 1].num[0] = tree[p].num[0]; tree[p << 1 | 1].num[0] = tree[p].num[0]; } } void build(int l, int r, int p) { tree[p].l = l; tree[p].r = r; tree[p].flag = 0; tree[p].cnt = 1; memset(tree[p].num, 0, sizeof(tree[p].num)); tree[p].num[0] = 2; if(l == r) { return ; } int mid = (l + r) >> 1; build(l, mid, p << 1); build(mid + 1, r, p << 1 | 1); } void update(int l, int r, int val, int p) { if(tree[p].l == l && tree[p].r == r) { memset(tree[p].num, 0, sizeof(tree[p].num)); tree[p].cnt = 1; tree[p].num[0] = val; tree[p].flag = 1; return ; } pushdown(p); int mid = (tree[p].l + tree[p].r) >> 1; if(r <= mid) update(l, r, val, p << 1); else if(l > mid) update(l,r,val,p << 1 | 1); else { update(l, mid, val, p << 1); update(mid + 1, r, val, p << 1 | 1); } pushup(p); } void query(int l, int r, int p) { if(tree[p].l == l && tree[p].r == r) { int i; for(i = 0; i < tree[p].cnt; i ++) { ans[tot++] = tree[p].num[i]; } sort(ans, ans + tot); tot = unique(ans, ans + tot) - ans; return ; } pushdown(p); int mid = (tree[p].l + tree[p].r) >> 1; if(mid >= r) query(l, r, p << 1); else if(l > mid) query(l, r, p << 1 | 1); else { query(l, mid, p << 1); query(mid + 1, r, p << 1 | 1); } } int main(int argc, char *argv[]) { #ifndef ONLINE_JUDGE freopen("in", "r", stdin); #endif int n, m, i, j; int hh; while(scanf("%d%d", &n, &m) != EOF) { if(n == 0 && m == 0) break; hh = 0; getchar(); for(i = 0; i < m; i ++) { scanf("%c", &op[i]); if(op[i] == 'P') { scanf("%d%d%d", &a[i], &b[i], &c[i]); Hash[hh++] = a[i]; Hash[hh++] = b[i]; } else { scanf("%d%d", &a[i], &b[i]); Hash[hh++] = a[i]; Hash[hh++] = b[i]; } getchar(); } sort(Hash, Hash + hh); hh = unique(Hash, Hash + hh) - Hash; build(1, hh, 1); for(i = 0; i < m; i ++) { a[i] = lower_bound(Hash, Hash + hh, a[i] ) - Hash + 1; b[i] = lower_bound(Hash, Hash + hh, b[i] ) - Hash + 1; } for(i = 0; i < m; i++) { if(op[i] == 'P') { update(a[i], b[i], c[i], 1); } else { memset(ans, 0, sizeof(ans)); tot = 0; query(a[i], b[i], 1); for(j = 0; j < tot; j ++) { if(j == 0) printf("%d", ans[0]); else printf(" %d", ans[j]); } printf("\n"); } } } }
HDU 5023 A Corrupt Mayor's Performance Art (线段树)
原文:http://blog.csdn.net/u012150279/article/details/39435833