一组数列,有区间修改和区间询问两种操作
算法:线段树+状态压缩+区间更新
很明显区间更新的线段树,每次询问的不是颜色的个数,而是有哪些颜色,所以如何记录颜色就成了问题,首先确定的是颜色的种类数比较小,我开始想到的是每一个节点开一个30的bool数组但是担心会爆内存,实际上也不好实现,所以另外寻找了状态压缩的方法,把三十个颜色状态压缩成一个long long的数,因为 2 ^ 30 = 1 073 741 824。然后就是区间更新了,合并的时候注意是两个孩子的或,当然bool数组一个一个来也可以,我感觉。其他都挺常规的。没看板子,尝试独立写了两个多小时。。。。。还是太菜。
注:我认为以下的代码可以当板子,谢谢啦
AC代码:
#includeusing namespace std; #define met(a, b) memset(a, b, sizeof(a)) const int maxn = 1e6 + 10; typedef long long ll; struct TREENODE { ll color; int l, r; int lchild, rchild; }treeNode[maxn << 2]; int lazy[maxn << 2]; void pushDown(int root, int color); void buildTree(int root, int l, int r); void update(int root, int l, int r, int color); ll query(int root, int l, int r); int main() { int N, Q, l, r, c; char s[2]; vector ans; while(~scanf("%d%d", &N, &Q) && N + Q) { buildTree(1, 1, N); while(Q--) { scanf("%s", s); if(s[0] == 'P') { scanf("%d%d%d", &l, &r, &c); update(1, l, r, c); // for(int i = 1; i <= 9; i++) { // cerr <> j) & 1) { ans.push_back(j); } } int len = ans.size(); for(int i = 0; i < len; i++) { printf("%d", ans[i]); if(i != len - 1) printf(" "); } puts(""); } } } return 0; } void buildTree(int root, int l, int r) { lazy[root] = 0; if(l == r) { treeNode[root].l = l; treeNode[root].r = r; treeNode[root].color = 1 << 2; return ; } treeNode[root].l = l; treeNode[root].r = r; treeNode[root].color = 1 << 2; int MID = (l + r) / 2; buildTree(root << 1, l, MID); buildTree(root << 1 | 1, MID + 1, r); treeNode[root].color = treeNode[root << 1].color | treeNode[root << 1 | 1].color; } void pushDown(int root, int color) { if(lazy[root] != 0) { lazy[root << 1] = lazy[root]; lazy[root << 1 | 1] = lazy[root]; treeNode[root << 1].color = 1 << color; treeNode[root << 1 | 1].color = 1 << color; lazy[root] = 0; } } void update(int root, int l, int r, int color) { if(treeNode[root].l == l && treeNode[root].r == r) { treeNode[root].color = 1 << color; lazy[root] = color; return ; } pushDown(root, lazy[root]); int MID = (treeNode[root].l + treeNode[root].r) >> 1; if(r <= MID) { update(root << 1, l, r, color); } else if(l > MID) { update(root << 1 | 1, l, r, color); } else { update(root << 1, l, MID, color); update(root << 1 | 1, MID + 1, r, color); } treeNode[root].color = treeNode[root << 1].color | treeNode[root << 1 | 1].color; } ll query(int root, int l, int r) { if(treeNode[root].l == l && treeNode[root].r == r) { return treeNode[root].color; } pushDown(root, lazy[root]); int MID = (treeNode[root].l + treeNode[root].r) / 2; if(r <= MID) { return query(root << 1, l, r); } else if(l > MID) { return query(root << 1 | 1, l, r); } else { return query(root << 1, l, MID) | query(root << 1 | 1, MID + 1, r); } }