B - A Corrupt Mayor's Performance Art HDU - 5023

题意:一组数列,有区间修改和区间询问两种操作
算法:线段树+状态压缩+区间更新
很明显区间更新的线段树,每次询问的不是颜色的个数,而是有哪些颜色,所以如何记录颜色就成了问题,首先确定的是颜色的种类数比较小,我开始想到的是每一个节点开一个30的bool数组但是担心会爆内存,实际上也不好实现,所以另外寻找了状态压缩的方法,把三十个颜色状态压缩成一个long long的数,因为 2 ^ 30 = 1 073 741 824。然后就是区间更新了,合并的时候注意是两个孩子的或,当然bool数组一个一个来也可以,我感觉。其他都挺常规的。没看板子,尝试独立写了两个多小时。。。。。还是太
:我认为以下的代码可以当板子,谢谢啦
AC代码:

#include <bits/stdc++.h>
using 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<int> 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 <<i<< ": "<< lazy[i] << endl;
               // }
            } else {
                ans.clear();
                scanf("%d%d", &l, &r);
                ll hasColor = query(1, l, r);
                //cout << hasColor << endl;
                for(int j = 1; j <= 30; j++) {
                    if((hasColor >> 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);
    }
}

猜你喜欢

转载自blog.csdn.net/m0_38081836/article/details/80530172