求助过不了样例,11 10 24
查看原帖
求助过不了样例,11 10 24
1126325
Indestructible楼主2024/4/15 20:00
#include<bits/stdc++.h>
#define int long long  // 开 long long 
#define maxn 100005    // 本题 n <= 1e5 
#define ls(x) (x<<1)   // 左子树 
#define rs(x) (x<<1|1) // 右子树 
// for 循环简便写法 
#define fr(i,x,y) for(int i=(x);i<=(y);i++)
using namespace std;
// 定义线段树框架变量 
int tree[maxn<<2],tag[maxn<<2];
int num[maxn],n,m;
// 建线段树 
int build(int l,int r,int id){
	// 递归结束:只有一个节点 
	if (l==r) return tree[id]=num[l];
	int mid=(l+r)>>1;
	// 向左右递归 
	build(l,mid,ls(id));
	build(mid+1,r,rs(id));
	// 赋值 
	return tree[id]=tree[ls(id)]+tree[rs(id)];
}
// 给节点 p 打 tag 标记 
void addtag(int p,int x,int y,int k){
	tag[p]+=k;          // 打 tag 
	tree[p]+=k*(y-x+1); // 计算新的 tree[p] 
}
// 下传 tag 
void pushdown(int p,int x,int y){
	if (tag[p]){
		int mid=(x+y)>>1;
		addtag(ls(p),x,mid,tag[p]);
		addtag(rs(p),mid+1,y,tag[p]);
		tag[p]=0;
	} 
}
// 将区间 [x,y] 的每个数加 k,现在节点是 id,表示 [l,r] 的区间和 
void update(int l,int r,int id,int x,int y,int k){
	// 完全覆盖,打 tag,返回 
	if (l<=x && r>=y){ addtag(id,x,y,k); return; }
	pushdown(id,l,r);
	int mid=(l+r)>>1;
	// 向左右递归 
	update(l,mid,ls(id),x,y,k);
	update(mid+1,r,rs(id),x,y,k);
	// 赋值 
	tree[id]=tree[ls(id)]+tree[rs(id)];
}
// 查询区间 [x,y] 的和,现在节点是 id,表示 [l,r] 的区间和
int query(int l,int r,int x,int y,int id){
	if (x<=l && y>=r) return tree[id];
	pushdown(id,l,r);
	int mid=(l+r)>>1,p=0;
	// 向左右递归
	if (x<=mid) p+=query(l,mid,x,y,ls(id));
	if (y>mid) p+=query(mid+1,r,x,y,rs(id));
	// 返回值
	return p;
}
signed main(){
	int n,m;
	scanf("%lld%lld",&n,&m);
	fr(i,1,n) scanf("%lld",&num[i]);
	build(1,n,1); // 建树 
	int op,x,y,k;
	fr(i,1,m){
		scanf("%lld",&op);
		if (op==1){ // 区间修改 
			scanf("%lld%lld%lld",&x,&y,&k);
			update(1,n,1,x,y,k);
		}else{ // 区间查询 
			scanf("%lld%lld",&x,&y);
			printf("%lld\n",query(1,n,x,y,1));
		}
	}
	return 0;
}
2024/4/15 20:00
加载中...