P3372求助
  • 板块学术版
  • 楼主Indestructible
  • 当前回复2
  • 已保存回复2
  • 发布时间2024/4/16 19:30
  • 上次更新2024/4/16 21:07:16
查看原帖
P3372求助
1126325
Indestructible楼主2024/4/16 19:30
#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) // 右子树 
using namespace std;
// 定义线段树框架变量 
int num[maxn],n,m,op,x,y,k;
int tree[maxn<<2],tag[maxn<<2];
// 更新 tree[p] 
void pushup(int p){
	tree[p]=tree[ls(p)]+tree[rs(p)];
}
// 建线段树 
void build(int pl,int pr,int p){
	if (pl==pr){ tree[p]=num[pl]; return; }
	int mid=(pl+pr)>>1;
	build(pl,mid,ls(p));
	build(mid+1,pr,rs(p));
	pushup(p);
}
// 给节点 p 打 tag 标记 
void addtag(int pl,int pr,int p,int k){
	tag[p]+=k,tree[p]+=(pr-pl+1)*k;
}
// 下传 tag 
void pushdown(int pl,int pr,int p){
	if (tag[p]){
		int mid=(pl+pr)>>1;
		addtag(pl,mid,ls(p),tag[p]);
		addtag(mid+1,pr,rs(p),tag[p]);
		tag[p]=0;
	}
}
// 将区间 [l,r] 的每个数加 k,现在节点是 p,表示 [pl,pr] 的区间和 
void update(int pl,int pr,int p,int l,int r,int k){
	if (l<=pl && r>=pr){ addtag(pl,pr,p,k); return; }
	pushdown(pl,pr,p);
	int mid=(pl+pr)>>1;
	if (l<=mid) update(pl,mid,ls(p),l,r,k);
	if (r>mid) update(mid+1,pr,rs(p),l,r,k);
	pushup(p);
}
// 查询区间 [l,r] 的和,现在节点是 p,表示 [pl,pr] 的区间和
int query(int pl,int pr,int p,int l,int r){
	if (l<=pl && r>=pr) return tree[p];
	pushdown(pl,pr,p);
	int mid=(pl+pr)>>1,ans=0;
	if (l<=mid) ans+=query(pl,mid,ls(p),l,r);
	if (r>mid) ans+=query(mid+1,pr,rs(p),l,r);
	return ans;
}
signed main(){
	scanf("%lld%lld",&n,&m);
	for (int i=1;i<=n;i++) scanf("%lld",&num[i]);
	for (int i=1;i<=m;i++){
		scanf("%lld%lld%lld",&op,&x,&y);
		if (op==1) scanf("%lld",&k),update(1,n,1,x,y,k); // 区间修改 
		else printf("%lld\n",query(1,n,1,x,y)); // 区间查询 
	}
	return 0;
}
2024/4/16 19:30
加载中...