树状数组3区间查询区间修改
Description
要求使用树状数组完成区间之和查询,区间加上某一相同数值的操作。
Solution
树状数组是用来单点加,查前缀和的。若要实现区间加,可以将原数列差分,然后在l位置处+val,在r+1处-val,这时要查询的就成了在差分数列上前缀和的前缀和,即二阶前缀和。
对于第i位来讲,它的值是这样组成的。
化简一下
再化简一下
此时就比较明了了,现在就是是要求 以及 这两个前缀和。第二个其实和第一没有什么本质区别,就是在给某一位加上val时,给第二个的前缀和加上i*val
#include<iostream> using namespace std; const int N = 1e6+10; int n; int A[N]; long long tr1[N] , tr2[N]; inline int lowbit(int x) { return x & (-x); } inline void Add(int pos , int val) { long long val2 = 1ll * val * pos; while(pos <= n) { tr1[pos] += val; tr2[pos] += val2; pos += lowbit(pos); } } inline long long Ask1(int pos) { long long Ans = 0; while(pos) { Ans += tr1[pos]; pos -= lowbit(pos); } return Ans; } inline long long Ask2(int pos) { long long Ans = 0; while(pos) { Ans += tr2[pos]; pos -= lowbit(pos); } return Ans; } inline long long Ask(int l , int r) { long long res1 = Ask1(r) * (r + 1) - Ask1(l-1) * l; long long res2 = Ask2(r) - Ask2(l-1); return res1 - res2; } int main() { int Q , op , l , r , x; cin >> n >> Q; for(int i = 1 ; i <= n ; ++i) cin >> A[i]; for(int i = n ; i >= 2 ; --i) A[i] = A[i] - A[i-1]; for(int i = 1 ; i <= n ; ++i) Add(i , A[i]); while(Q--) { cin >> op >> l >> r; if(op == 1) { cin >> x; Add(l , x); Add(r + 1 , -x); } else cout << Ask(l , r) << '\n'; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具