luokes @ 2023-03-23 16:25:40
代码实现如下:
using namespace std;
#define NMAX 100000 // n 的最大值
int m,n,t;
long long int nums[NMAX+1];
long long int f[NMAX*4+1]; // 线段树的节点,开始编号为 1,最大为 n*4+1
// k 为当前节点的标号
// l 为当前节点区间的左边界
// r 为当前节点区间的右边界
void build_tree(int k,int l,int r)
0{
// 如果到达了叶子节点
if(r == l)
{
f[k] = nums[l];
return;
}
// 其它
int m = (l+r) >> 1;
build_tree(k<<1,l,m); // 左孩子
build_tree(k<<1|1,m+1,r); // 右孩子
f[k] = f[k<<1] + f[k<<1|1]; // 父亲的值为两孩子的和
}
// 修改编号为 k,区间为 [l,k]的树的 [x,y]区间 中值
void add(int k,int l,int r,int x,int y)
{
f[k] += (y-x+1)*t;
// 到达了叶节点
if(r == l) return;
int m = (r+l) >> 1;
if(y <= m) add(k<<1,l,m,x,y); // 如果完全坐落树的左边
else if(x > m) add(k<<1|1,m+1,r,x,y); // 如果完全坐落树的右边
else // 两边都有
{
add(k<<1,l,m,x,m);
add(k<<1|1,m+1,r,m+1,y);
}
}
// 查询编号为 k,区间为 [l,k]的树的 [x,y]区间 中值
int calc(int k,int l,int r,int x,int y)
{
// 如果为 K 节点
if(l == x && r == y) return f[k];
int m = (r+l) >> 1;
if(y <= m) return calc(k<<1,l,m,x,y); // 如果完全坐落树的左边
else if(x > m) return calc(k<<1|1,m+1,r,x,y); // 如果完全坐落树的右边
else return calc(k<<1,l,m,x,m)+calc(k<<1|1,m+1,r,m+1,y); // 两边都有
}
int main()
{
cin >> n >> m;
// [1] 获取数据并进行建树
for(int i = 1;i <= n;i++)
{
cin >> nums[i];
}
build_tree(1,1,n);
for(int i = 0;i < m;i++)
{
int op,x,y;
cin >> op >> x >> y;
if(op == 1) // [2] 维护树
{
cin >> t;
add(1,1,n,x,y);
}
else // [3] 搜索树
{
cout << (calc(1,1,n,x,y)) << endl;
}
}
return 0;
}
by wenqizhi1125 @ 2023-03-23 16:33:00
区间加操作复杂度是
by luokes @ 2023-03-23 16:41:41
@wenqizhi1125 好的,谢谢大佬
by comcopy @ 2023-03-23 16:46:27
咦我记得单点修改能过得
by yonghang @ 2023-03-26 08:56:05
对哦!忘了lazy标记!