每个数最多取log次就会编程10000(2),如果是这种数字的话直接可以打一个标记,我们直接乘2,这样不必每个数都加lowbit
传送门
/*
* @Author: 0iq_love_zy
* @LastEditTime: 2021-06-16 17:55:19
* @优快云 blog: https://blog.youkuaiyun.com/acm_durante
* @E-mail: 1055323152@qq.com
* @ProbTitle:
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define lowbit(x) ((x) & -(x))
const ll mod = 998244353;
ll powmod(ll a, ll b)
{
ll res = 1;
a %= mod;
assert(b >= 0);
for (; b; b >>= 1)
{
if (b & 1)
res = res * a % mod;
a = a * a % mod;
}
return res;
}
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
template <class T>
inline void read(T &res)
{
char c;
T flag = 1;
while ((c = getchar()) < '0' || c > '9')
if (c == '-')
flag = -1;
res = c - '0';
while ((c = getchar()) >= '0' && c <= '9')
res = res * 10 + c - '0';
res *= flag;
}
const int N = 1e5 + 50;
int n, m;
struct node
{
int l, r;
ll x, sum;
int lazy;
int flag;
} tree[N << 2];
void push_up(int p)
{
tree[p].sum = (tree[p << 1].sum + tree[p << 1 | 1].sum) % mod;
tree[p].flag = (tree[p << 1].flag & tree[p << 1 | 1].flag);
}
void push_down(int p)
{
if (tree[p].lazy == 0)
return;
tree[p << 1].lazy += tree[p].lazy;
tree[p << 1 | 1].lazy += tree[p].lazy;
tree[p << 1].sum = (tree[p << 1].sum * powmod(2, tree[p].lazy)) % mod;
tree[p << 1 | 1].sum = (tree[p << 1 | 1].sum * powmod(2, tree[p].lazy)) % mod;
tree[p].lazy = 0;
}
void build_tree(int l, int r, int p)
{
tree[p].l = l, tree[p].r = r;
tree[p].lazy = tree[p].flag = 0;
if (l == r)
{
scanf("%lld", &tree[p].x);
tree[p].sum = tree[p].x;
if (lowbit(tree[p].x) == tree[p].x)
tree[p].flag = 1;
return;
}
int mid = l + r >> 1;
build_tree(l, mid, p << 1);
build_tree(mid + 1, r, p << 1 | 1);
push_up(p);
}
void update_tree(int l, int r, int p)
{
if (l <= tree[p].l && tree[p].r <= r && tree[p].flag)
{
tree[p].sum = (tree[p].sum * 2) % mod;
tree[p].lazy++;
return;
}
if (tree[p].l == tree[p].r)
{
tree[p].x = tree[p].sum = tree[p].sum + lowbit(tree[p].sum);
if (lowbit(tree[p].x) == tree[p].x)
tree[p].flag = 1;
return;
}
push_down(p);
int mid = (tree[p].l + tree[p].r) >> 1;
if (l <= mid)
update_tree(l, r, p << 1);
if (mid < r)
update_tree(l, r, p << 1 | 1);
push_up(p);
}
ll ask_sum(int l, int r, int p)
{
if (l <= tree[p].l && tree[p].r <= r)
{
return tree[p].sum;
}
ll res = 0;
push_down(p);
int mid = (tree[p].l + tree[p].r) >> 1;
if (l <= mid)
res = (res + ask_sum(l, r, p << 1)) % mod;
if (mid < r)
res = (res + ask_sum(l, r, p << 1 | 1)) % mod;
return res;
}
void solve()
{
scanf("%d", &n);
build_tree(1, n, 1);
scanf("%d", &m);
int op, l, r;
for (int i = 1; i <= m; i++)
{
scanf("%d%d%d", &op, &l, &r);
if (op == 1)
{
update_tree(l, r, 1);
}
else
{
printf("%lld\n", ask_sum(l, r, 1));
}
}
}
int main()
{
int t;
while (~scanf("%d", &t))
{
while (t--)
{
solve();
}
}
return 0;
}
高效动态维护区间加法操作
这篇博客介绍了一种高效处理区间加法操作的方法,通过log次更新就能将数值变为10000(2)。文章详细阐述了如何使用二进制位运算和树状数组(区间更新和查询)来实现这一操作,并提供了C++代码实现。
305

被折叠的 条评论
为什么被折叠?



