LibreOJ#132. 树状数组 3 :区间修改,区间查询
【区间修改,区间查询】
https://loj.ac/p/132
题意
解析
代码
做的时候是按照洛谷线段树1那题做的,范围10^18。但其实会有问题,求和过程中可能会爆longlong。
求一次前缀,实际上就是
这是sum(k)
区间查询 就是求 sum(r) - sum(l)
用两个树状数组,一个实现 另一个实现(i-1)*
方便无脑,直接搞两个add和sum。其实也可以用传数组的形式。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
ll tr1[N],tr2[N],n,m;
int lowbit(ll x){
return x & -x;
}
void add1(ll x,ll k){
while(x <= n){
tr1[x] += k;
x = x + lowbit(x);
}
}
void add2(ll x,ll k){
while(x <= n){
tr2[x] += k;
x = x + lowbit(x);
}
}
ll sum1(ll x){
ll ans = 0;
while(x >= 1){
ans += tr1[x];
x = x - lowbit(x);
}
return ans;
}
ll sum2(ll x){
ll ans = 0;
while(x >= 1){
ans += tr2[x];
x = x - lowbit(x);
}
return ans;
}
int main(){
scanf("%lld %lld",&n,&m);
int last = 0;
for(int i=1;i<=n;i++){
ll x;
scanf("%lld",&x);
add1(i,x-last);
add2(i,(x-last)*(i-1));
last = x;
}
while(m--){
ll op,x,y,k;
scanf("%lld %lld %lld",&op,&x,&y);
if(op == 1){
scanf("%lld",&k);
add1(x,k);
add1(y+1,-k);
add2(x,k*(x-1));//维护(i-1)*D[i]
add2(y+1,-k*y);//k*y = k*((y+1)-1)
}else{
//注意 如果范围比较大 y * sum1(y) 会爆longlong
printf("%lld\n", y*sum1(y)-(x-1)*sum1(x-1)-(sum2(y)-sum2(x-1)));
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探