LAZY_TAG

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=100000+10;
typedef long long ll;
ll a[maxn];
ll tree[maxn<<2];
ll lazy[maxn<<2];
void build(ll h,ll l,ll r){
	if(l==r){
		tree[h]=a[l];
		return ;
	}
	ll mid=(l+r)>>1;
	build(h<<1,l,mid);
	build(h<<1|1,mid+1,r);
	tree[h]=tree[h<<1]+tree[h<<1|1];
}
void updata(ll h,ll l,ll r,ll q,ll w,ll e){
	if(l==q&&r==w){	
		lazy[h]+=e;
		return ;
	}
	ll mid=(l+r)>>1;
	tree[h]+=(w-q+1)*e;
	if(q>mid)updata(h<<1|1,mid+1,r,q,w,e);
	else if(w<=mid)updata(h<<1,l,mid,q,w,e);
	else{
		updata(h<<1,l,mid,q,mid,e);
		updata(h<<1|1,mid+1,r,mid+1,w,e);
	}
}
ll query(ll h,ll l,ll r,ll q,ll w){
	if(l==q&&r==w){
		return tree[h]+lazy[h]*(w-q+1);
	}
	ll mid=(l+r)>>1;
	if(lazy[h]){
		tree[h]+=lazy[h]*(r-l+1);
		updata(h<<1,l,mid,l,mid,lazy[h]);
		updata(h<<1|1,mid+1,r,mid+1,r,lazy[h]);
		lazy[h]=0;
	}
	if(q>mid)return query(h<<1|1,mid+1,r,q,w);
	else if(w<=mid)return query(h<<1,l,mid,q,w);
	else return query(h<<1,l,mid,q,mid)+query(h<<1|1,mid+1,r,mid+1,w); 
}
int main(){
	ll i,j,k,m,n;
	scanf("%lld%lld",&n,&m);
	for(i = 1;i <= n;i++)scanf("%lld",&a[i]);
	build(1,1,n);
	while(m--){
		ll q,w,e;
		ll t;
		scanf("%lld",&t);
		if(t==1){
			scanf("%lld%lld%lld",&q,&w,&e);
			updata(1,1,n,q,w,e);
		}
		if(t==2){
			scanf("%lld%lld",&q,&w);
			printf("%lld\n",query(1,1,n,q,w));
		}	
	}
	return 0;
}

转载于:https://www.cnblogs.com/brodrinkwater/p/7527994.html

使代码定义的变量不超过2字母 ````cpp ```cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 50005; // 数组最大长度 int n, BLOCK_SIZE; long long arr[MAX_N]; // 原始数组 long long block_sum[320]; // 每个块的当前总和 long long lazy_tag[320]; // 每个块的懒标记 // 初始化分块 void build_blocks() { for (int i = 0; i < n; ++i) { block_sum[i / BLOCK_SIZE] += arr[i]; // 累积每个块内的数值 } } // 将懒惰标记下放给具体元素 void push_down(int blk_id) { if (lazy_tag[blk_id]) { int start = blk_id * BLOCK_SIZE; // 当前块起始位置 int end = min(start + BLOCK_SIZE, n); // 当前块结束位置 for (int j = start; j < end; ++j) { // 遍历并更新单个元素 arr[j] += lazy_tag[blk_id]; } block_sum[blk_id] += lazy_tag[blk_id] * (end - start); // 更新块总和 lazy_tag[blk_id] = 0; // 清空懒标记 } } // 区间加法操作 [L, R] 加上值 c void update_range_addition(int L, int R, long long add_val) { int left_blk = L / BLOCK_SIZE; int right_blk = R / BLOCK_SIZE; if (left_blk == right_blk) { // 同一区块的情况 for (int i = L; i <= R; ++i) { arr[i] += add_val; } block_sum[left_blk] += (R - L + 1) * add_val; // 直接修改块总和 } else { // 跨越多个区块的情况 // 修改左端点所在的不完整块 for (int i = L; i < (left_blk + 1) * BLOCK_SIZE && i <= R; ++i) { arr[i] += add_val; } block_sum[left_blk] += ((left_blk + 1) * BLOCK_SIZE - L) * add_val; // 修改中间完整的块 for (int blk = left_blk + 1; blk < right_blk; ++blk) { lazy_tag[blk] += add_val; // 打上懒标记 block_sum[blk] += BLOCK_SIZE * add_val; // 修改块总和 } // 修改右端点所在的不完整块 for (int i = right_blk * BLOCK_SIZE; i <= R; ++i) { arr[i] += add_val; } block_sum[right_blk] += (R - right_blk * BLOCK_SIZE + 1) * add_val; } } // 区间求和操作 [L, R] long long query_range_sum(int L, int R, long long mod_value) { long long res = 0; int left_blk = L / BLOCK_SIZE; int right_blk = R / BLOCK_SIZE; if (left_blk == right_blk) { // 同一区块的情况 for (int i = L; i <= R; ++i) { res += arr[i]; } } else { // 跨越多个区块的情况 // 计算左端点所在的不完整块 for (int i = L; i < (left_blk + 1) * BLOCK_SIZE; ++i) { res += arr[i]; } // 计算中间完整块的结果 for (int blk = left_blk + 1; blk < right_blk; ++blk) { res += block_sum[blk] + lazy_tag[blk] * BLOCK_SIZE; } // 计算右端点所在的不完整块 for (int i = right_blk * BLOCK_SIZE; i <= R; ++i) { res += arr[i]; } } return res % mod_value; // 返回取模后的结果 } // 主函数入口 int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n; // 输入数组大小 BLOCK_SIZE = sqrt(n); // 设置块大小 for (int i = 0; i < n; ++i) { cin >> arr[i]; // 输入数组内容 } build_blocks(); // 构建分块结构 for (int q = 0; q < n; ++q) { int opt, l, r, c; cin >> opt >> l >> r >> c; --l; --r; // 将索引从 1-based 改为 0-based if (opt == 0) { update_range_addition(l, r, c); // 区间加法 } else if (opt == 1) { cout << query_range_sum(l, r, c + 1) << "\n"; // 区间求和并输出结果 } } return 0; } ```
最新发布
04-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值