FZU - 2105 - Digits Count - 线段树

http://acm.fzu.edu.cn/problem.php?pid=2105
这个是有点东西,分解位操作之后要考虑lazy的影响,假如不顾一切往下PushDown的话要先判断叶子,叶子是不能PushDown的。其次要Build的时候清空lazy。不顾一切先PushDown并不能改变运算符优先级的影响,因为子树也可能有lazy标记。所以当时银川重赛弄的那个是白弄的。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;

const int MAXN = 1e6;
const int MAXLOGAI = 4;

int a[MAXN + 5];
int st[MAXN * 4 + 5][MAXLOGAI];
char lazy[MAXN * 4 + 5][MAXLOGAI];

inline void PushUp(int o) {
    for(int id = 0; id < MAXLOGAI; ++id)
        st[o][id] = st[o << 1][id] + st[o << 1 | 1][id];
}

inline void PushDown(int o, int l, int r) {
    for(int id = 0; id < MAXLOGAI; ++id) {
        if(lazy[o][id]) {
            int mid = l + r >> 1;
            if(lazy[o][id] == 1) {
                if(lazy[o << 1][id] == 0) {
                    st[o << 1][id] = (mid - l + 1) - st[o << 1][id];
                    lazy[o << 1][id] = 1;
                } else if(lazy[o << 1][id] == 1) {
                    st[o << 1][id] = (mid - l + 1) - st[o << 1][id];
                    lazy[o << 1][id] = 0;
                } else if(lazy[o << 1][id] == 2) {
                    st[o << 1][id] = 0;
                    lazy[o << 1][id] = 3;
                } else if(lazy[o << 1][id] == 3) {
                    st[o << 1][id] = (mid - l + 1);
                    lazy[o << 1][id] = 2;
                }

                if(lazy[o << 1 | 1][id] == 0) {
                    st[o << 1 | 1][id] = (r - (mid + 1) + 1) - st[o << 1 | 1][id];
                    lazy[o << 1 | 1][id] = 1;
                } else if(lazy[o << 1 | 1][id] == 1) {
                    st[o << 1 | 1][id] = (r - (mid + 1) + 1) - st[o << 1 | 1][id];
                    lazy[o << 1 | 1][id] = 0;
                } else if(lazy[o << 1 | 1][id] == 2) {
                    st[o << 1 | 1][id] = 0;
                    lazy[o << 1 | 1][id] = 3;
                } else if(lazy[o << 1 | 1][id] == 3) {
                    st[o << 1 | 1][id] = (r - (mid + 1) + 1);
                    lazy[o << 1 | 1][id] = 2;
                }
            } else if(lazy[o][id] == 2) {
                st[o << 1][id] = (mid - l + 1);
                lazy[o << 1][id] = 2;
                st[o << 1 | 1][id] = (r - (mid + 1) + 1);
                lazy[o << 1 | 1][id] = 2;
            } else {
                st[o << 1][id] = 0;
                lazy[o << 1][id] = 3;
                st[o << 1 | 1][id] = 0;
                lazy[o << 1 | 1][id] = 3;
            }
            lazy[o][id] = 0;
        }
    }
}

void Build(int o, int l, int r) {
    for(int id = 0; id < MAXLOGAI; ++id)
        lazy[o][id] = 0;
    if(l == r) {
        for(int id = 0; id < MAXLOGAI; ++id)
            st[o][id] = (a[l] & (1 << id)) ? 1 : 0;
    } else {
        int mid = l + r >> 1;
        Build(o << 1, l, mid);
        Build(o << 1 | 1, mid + 1, r);
        PushUp(o);
    }
}

void Update(int o, int l, int r, int ql, int qr, int op, int x) {
    //op=1 ^
    //op=2 |
    //op=3 &
    if(l != r)
        PushDown(o, l, r);
    if(ql <= l && r <= qr) {
        if(op == 1) {
            for(int id = 0; id < MAXLOGAI; ++id) {
                if(x & (1 << id)) {
                    st[o][id] = (r - l + 1) - st[o][id];
                    lazy[o][id] = op;
                }
            }
        } else if(op == 2) {
            for(int id = 0; id < MAXLOGAI; ++id) {
                if(x & (1 << id)) {
                    st[o][id] = (r - l + 1);
                    lazy[o][id] = op;
                }
            }
        } else {
            for(int id = 0; id < MAXLOGAI; ++id) {
                if(!(x & (1 << id))) {
                    st[o][id] = 0;
                    lazy[o][id] = op;
                }
            }
        }
    } else {
        int mid = l + r >> 1;
        if(ql <= mid)
            Update(o << 1, l, mid, ql, qr, op, x);
        if(qr >= mid + 1)
            Update(o << 1 | 1, mid + 1, r, ql, qr, op, x);
        PushUp(o);
    }
}

ll Query(int o, int l, int r, int ql, int qr) {
    if(l != r)
        PushDown(o, l, r);
    if(ql <= l && r <= qr) {
        ll res = 0;
        for(int id = 0; id < MAXLOGAI; ++id)
            res += 1ll * (1 << id) * (st[o][id]);
        return res;
    } else {
        ll res = 0;
        int mid = l + r >> 1;
        if(ql <= mid)
            res += Query(o << 1, l, mid, ql, qr);
        if(qr >= mid + 1)
            res += Query(o << 1 | 1, mid + 1, r, ql, qr);
        return res;
    }
}

int main() {
#ifdef localll
    freopen("lyz.in", "r", stdin);
#endif // local
    int T, n, m;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);
        Build(1, 1, n);
        for(int i = 1; i <= m; ++i) {
            char ops[10];
            int l, r, x;
            scanf("%s", ops);
            if(ops[0] == 'S') {
                scanf("%d%d", &l, &r);
                ++l, ++r;
                printf("%lld\n", Query(1, 1, n, l, r));
            } else {
                scanf("%d%d%d", &x, &l, &r);
                ++l, ++r;
                if(ops[0] == 'X') {
                    Update(1, 1, n, l, r, 1, x);
                } else if(ops[0] == 'O') {
                    Update(1, 1, n, l, r, 2, x);
                } else if(ops[0] == 'A') {
                    Update(1, 1, n, l, r, 3, x);
                }
            }
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/Inko/p/11498889.html
今日推荐