大意:两种操作1给区间内所有ai加上lowbit(ai)
操作2:区间问询总和
lowbit的性质:lowbit(ai)会取ai二进制下的最高位的1,例如5的二进制是101,lowbit(5)=1,4的二进制是100,lowbit(4)=4;
用以下代码可以快速算出lowbit
int lowbit(int x) {
return x & (-x);
}
另一个性质:一个数最多进行加log次lowbit,二进制就会变成1000……000的形式,此时再加lowbit就是这个数乘2.
用线段树+懒标记维护区间,加上一个标记来标明这个区间是需要lowbit还是直接*2
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10, mod = 998244353;
int n, m;
int w[N];
struct node {
int num, l, r, ok, lazy;
} tr[4 * N];
int lowbit(int x) {
return x & (-x);
}
void pushup(int u) {
tr[u].num = (tr[u << 1].num + tr[u << 1 | 1].num) % mod;
if (tr[u << 1].ok && tr[u << 1 | 1].ok)
tr[u].ok = 1;
}
void pushdown(int u) {
if (tr[u].lazy <= 1)
return;
tr[u << 1].num = tr[u << 1].num * tr[u].lazy % mod;
tr[u << 1 | 1].num = tr[u << 1 | 1].num * tr[u].lazy % mod;
tr[u << 1].lazy = tr[u << 1].lazy * tr[u].lazy % mod;
tr[u << 1 | 1].lazy = tr[u << 1 | 1].lazy * tr[u].lazy % mod;
tr[u].lazy = 1;
}
void build(int u, int l, int r) {
tr[u] = {w[l], l, r, 0, 1};
if (l == r) {
if (tr[u].num == lowbit(tr[u].num))
tr[u].ok = 1;
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
return;
}
int query(int u, int l, int r) {
//cout << u << " " << l << " " << r << endl;
if (tr[u].l >= l && tr[u].r <= r) {
return tr[u].num % mod;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
int res = 0;
if (l <= mid)
res += query(u << 1, l, r) % mod;
if (r > mid)
res = (res + query(u << 1 | 1, l, r)) % mod;
return res;
}
void modify(int u, int l, int r) {
//cout << u << " " << l << " " << r << endl;
if (tr[u].l >= l && tr[u].r <= r && tr[u].ok) {
tr[u].num = (tr[u].num * 2) % mod;
tr[u].lazy = (tr[u].lazy * 2) % mod;
return;
}
if (tr[u].l == tr[u].r && tr[u].l >= l && tr[u].r <= r) {
tr[u].num += lowbit(tr[u].num);
if (tr[u].num == lowbit(tr[u].num)) {
tr[u].ok = 1;
tr[u].num %= mod;
}
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if (mid >= l) {
modify(u << 1, l, r);
}
if (mid < r) {
modify(u << 1 | 1, l, r);
}
pushup(u);
}
void prin() {
for (int i = 1; i <= n; i++) {
cout << query(1, i, i) << " ";
}
cout << endl;
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> w[i];
build(1, 1, n);
cin >> m;
while (m--) {
int a, b, c;
cin >> a >> b >> c;
//prin();
if (a == 1) {
modify(1, b, c);
} else {
cout << query(1, b, c) << endl;
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--) {
solve();
}
}