zoukankan      html  css  js  c++  java
  • FZU2105 Digits Count(按位建线段树)题解

    题意:

    给出区间与、或、异或(x)操作,还有询问区间和。

    思路:

    因为数比较小,我们给每一位建线段树,这样每次只要更新对应位的答案。
    (0)和或(1)相当于重置区间,异或(1)相当于翻转区间,那么设出两个(lazy)搞一下。注意父区间(pushdown)重置标记时,子区间的翻转标记要清空。

    代码:

    #include <map>
    #include <set>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <ctime>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    typedef long long ll;
    typedef unsigned long long ull;
    using namespace std;
    const int maxn = 1e6 + 5;
    const int MAXM = 3e6;
    const ll MOD = 1e9 + 7;
    const ull seed = 131;
    const int INF = 0x3f3f3f3f;
    
    #define lson (rt << 1)
    #define rson (rt << 1 | 1)
    int sum[5][maxn << 2];
    int lazy[5][maxn << 2], rev[5][maxn << 2];
    int a[maxn];
    void pushup(int rt, int bit){
        sum[bit][rt] = sum[bit][lson] + sum[bit][rson];
    }
    void pushdown(int rt, int bit, int l, int r){
        int m = (l + r) >> 1;
        if(lazy[bit][rt] != -1){
            sum[bit][lson] = lazy[bit][rt] * (m - l + 1);
            sum[bit][rson] = lazy[bit][rt] * (r - m);
            lazy[bit][lson] = lazy[bit][rson] = lazy[bit][rt];
            rev[bit][lson] = rev[bit][rson] = 0;    //!!!!!
            lazy[bit][rt] = -1;
        }
        if(rev[bit][rt]){
            sum[bit][lson] = m - l + 1 - sum[bit][lson];
            sum[bit][rson] = r - m - sum[bit][rson];
            rev[bit][lson] ^= 1;
            rev[bit][rson] ^= 1;
            rev[bit][rt] = 0;
        }
    }
    void build(int l, int r, int bit, int rt){
        lazy[bit][rt] = -1;
        rev[bit][rt] = 0;
        if(l == r){
            sum[bit][rt] = (a[l] >> bit) & 1;
            return;
        }
        int m = (l + r) >> 1;
        build(l, m, bit, lson);
        build(m + 1, r, bit, rson);
        pushup(rt, bit);
    }
    void update(int L, int R, int l, int r, int op, int bit, int rt){
        if(L <= l && R >= r){
            if(op == 1){    //&0
                lazy[bit][rt] = 0;
                rev[bit][rt] = 0;
                sum[bit][rt] = 0;
            }
            else if(op == 2){   //|1
                lazy[bit][rt] = 1;
                rev[bit][rt] = 0;
                sum[bit][rt] = r - l + 1;
            }
            else{   //^1
                rev[bit][rt] ^= 1;
                sum[bit][rt] = r - l + 1 - sum[bit][rt];
            }
            return;
        }
        pushdown(rt, bit, l, r);
        int m = (l + r) >> 1;
        if(L <= m)
            update(L, R, l, m, op, bit, lson);
        if(R > m)
            update(L, R, m + 1, r, op, bit, rson);
        pushup(rt, bit);
    }
    int query(int L, int R, int l, int r, int bit, int rt){
        if(L <= l && R >= r){
            return sum[bit][rt];
        }
        pushdown(rt, bit, l, r);
        int m = (l + r) >> 1, ret = 0;
        if(L <= m)
            ret += query(L, R, l, m, bit, lson);
        if(R > m)
            ret += query(L, R, m + 1, r, bit, rson);
        return ret;
    }
    int main(){
        int n, m, T;
        scanf("%d", &T);
        while(T--){
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
            for(int i = 0; i < 5; i++) build(1, n, i, 1);
            while(m--){
                int op, l, r, x;
                char ope[10];
                scanf("%s", &ope);
                if(ope[0] == 'A') op = 1;
                else if(ope[0] == 'O') op = 2;
                else if(ope[0] == 'X') op = 3;
                else op = 4;
                if(op == 4){
                    scanf("%d%d", &l, &r);
                    l++, r++;
                    ll ans = 0;
                    for(int i = 0; i < 5; i++){
                        x = query(l, r, 1, n, i, 1);
                        ans += 1LL * (1LL << i) * x;
                    }
                    printf("%lld
    ", ans);
                }
                else{
                    scanf("%d%d%d", &x, &l, &r);
                    l++, r++;
                    if(op == 2 || op == 3){
                        for(int i = 0; i < 5; i++){
                            if((x >> i) & 1)
                                update(l, r, 1, n, op, i, 1);
                        }
                    }
                    else{
                        for(int i = 0; i < 5; i++){
                            if(!((x >> i) & 1))
                                update(l, r, 1, n, op, i, 1);
                        }
                    }
                }
            }
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    用jmeter进行多用户并发压力测试 [转]
    jmeter 压力测试 参数
    web测试 结果存储类型为“Database”,但尚未指定结果储存库连接字符串
    apache配置多站点
    seajs + easyui [转]
    js,this,constrct ,prototype
    js call apply
    js this [转]
    [leetcode] Longest Common Prefix @ Python
    [leetcode] path sum @ Python [recursion]
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11489274.html
Copyright © 2011-2022 走看看