lowbit

2021 CCPC Northeast Invitational Contest D

Problem Statement

Lucida has a sequence of $n$ integers $a_1, a_2, \dots, a_n$. He asks you to perform two types of operations for him, which are described as follows:

1. 1 L R, add $lowbit(a_i)$ to each $a_i$ in the interval $[L, R]$.

2. 2 L R, query the sum of the numbers in the interval $[L, R]$.

$lowbit(x)$ is defined as the largest power of 2 that divides $x$. For example, lowbit(4)=4, lowbit(5)=1. Specially, lowbit(0)=0.

Lucida wants you to give the answer modulo $998244353$ for each of his queries.

Input

This problem contains multiple test cases.

The first line contains a single integer $T$ ($1\leq T \leq 20$) indicating the number of test cases.

For each case, the first line contains an integer $n$ ($1 \leq n \leq 10^5$), the length of the sequence.

The next line contains $n$ integers $a_i$ ($1 \leq a_i < 998244353$) separated by spaces, representing the sequence.

The next line contains an integer $m$ ($1 \leq m \leq 10^5$), the number of operations.

The next $m$ lines, each line contains 3 integers $op, L, R$ ($1 \leq op \leq 2$, $1 \leq L \leq R \leq n$), represents one operation. The specific meaning is described above.

Output

For each query, output a line contains the answer modulo $998244353$.

Solving

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#define ls(p) (p << 1)
#define rs(p) (p << 1 | 1)
//#define Single
const ll MOD = 998244353;
const int N = 1e5+1;
// 区间为二的幂直接乘2,否则直接暴力修改
bool check(int x) {return (x & (x - 1)) == 0;} // 判断是否为2的某次幂
int lowbit(int x) {return x & -x;} 
struct SegTree
{
    private:
        struct Node
        {
            int l,r;
            int lazymul; // 区间乘懒标记
            int sum;
            bool tag; // 是否为二的幂值区间
            Node() : l(0),r(0),lazymul(1),sum(0),tag(false) {}
        }tree[N<<2];
        vector<int> arr;
        void push_up(int p)
        {
            tree[p].sum = (tree[ls(p)].sum + tree[rs(p)].sum) % MOD;
            tree[p].tag = tree[ls(p)].tag & tree[rs(p)].tag;
        }
        void apply_mul(int p,int val)
        {
            tree[p].sum = (tree[p].sum * val) % MOD;
            tree[p].lazymul = (tree[p].lazymul * val) % MOD;
        }
        void push_down(int p)
        {
            if(tree[p].lazymul != 1)
            {
                apply_mul(ls(p),tree[p].lazymul);
                apply_mul(rs(p),tree[p].lazymul);
                tree[p].lazymul = 1;
            }
        }
    public:
        SegTree(const vector<int>& _arr) : arr(_arr)
        {
            build(1,1,(int)arr.size()-1);
        }
        void build(int p,int l,int r)
        {
            tree[p].l = l;
            tree[p].r = r;
            if(l == r)
            {
                tree[p].sum = arr[l];
                tree[p].tag = check(arr[l]);
                return; 
            }
            int mid = (l + r) >> 1;
            build(ls(p),l,mid);
            build(rs(p),mid+1,r);
            push_up(p);
        }
        void updateAdd(int p,int ul,int ur)
        {   
            //如果该区间是二的幂区间,区间乘2修改
            if(ul <= tree[p].l && tree[p].r <= ur && tree[p].tag)
            {
                tree[p].sum = (tree[p].sum * 2) % MOD;
                tree[p].lazymul = (tree[p].lazymul * 2) % MOD;
                // tree[p].tag = check(tree[p].sum);
                // 不能加,区间和是二的次幂不代表每个元素都是二的次幂
                return;
            }
            //否则暴力修改单个元素的值
            if(tree[p].l == tree[p].r)
            {
                tree[p].sum += lowbit(tree[p].sum);
                tree[p].tag = check(tree[p].sum);
                return;
            }
            push_down(p);
            int mid = (tree[p].l + tree[p].r) >> 1;
            if(ul <= mid) updateAdd(ls(p),ul,ur);
            if(mid < ur) updateAdd(rs(p),ul,ur);
            push_up(p);
        }
        int querySum(int p,int ql,int qr)
        {
            if(ql <= tree[p].l && tree[p].r <= qr) return tree[p].sum % MOD;
            push_down(p);
            int mid = (tree[p].l + tree[p].r) >> 1;
            int res = 0;
            if(ql <= mid) res = (res + querySum(ls(p),ql,qr)) % MOD;
            if(mid < qr) res = (res + querySum(rs(p),ql,qr)) % MOD;
            return res; 
        }
};
Licensed under CC BY-NC-SA 4.0
Member of the Qilu University Of Technology ACM-ICPC Association
Built with Hugo
Theme Stack designed by Jimmy