没过样例做法树状数组,悬赏1关注
查看原帖
没过样例做法树状数组,悬赏1关注
502758
ForMyDream楼主2023/1/15 14:00
#include<iostream>
using namespace std;
#define lowbit(x) ((x)&-(x))
#define ll long long 
#define maxn 100010

ll tree1[maxn],tree2[maxn],n,m; 

// 在差分数组[x] 的位置增加 d
// 差分数组在这里没有表示出来,因为差分数组就是用 tree 来维护的,tree 就是差分数组+树状数组
void update1(ll x,ll d){
	// 在差分数组[x] 的位置增加 d
	// 差分数组在这里没有表示出来,因为差分数组就是用 tree 来维护的,tree 就是差分数组+树状数组
	while (x<=maxn){
		tree1[x]+=d; x+=lowbit(x);
	}
}

void update2(ll x,ll d){
	while (x<=maxn){
		tree2[x]+=d; x+=lowbit(x);
	}
}

ll sum1(ll x){
	ll ans=0;
	while (x>0){
		ans+=tree1[x]; x-=lowbit(x);
	}
	return ans;
}

ll sum2(ll x){
	ll ans=0;
	while (x>0){
		ans+=tree2[x]; x-=lowbit(x);
	}
	return ans;
}

int main(){
	ios::sync_with_stdio(false);
	// 不用建立原数组了,可以直接将原数组的值代入 tree 中
	cin>>n>>m;
	ll a,old; // a 用于输入原数组的数据,old 存储原数组的上一个元素,用于构造差分
	for (int i=1;i<=n;i++){
		cin>>a;
		update1(i,a-old); // 构造差分 差分[i]=原[i]-原[i-1] 
		update2(i,(i-1)*(a-old)); // 一开始就把 i-1 乘进去 
		old=a; 
	} 
//	cout<<sum1(3)<<endl;
	while (m--){
		ll q,l,r,d;
		cin>>q;
		if (q==1){
			cin>>l>>r>>d;
			update1(l,d);
			update1(r+1,-d); // 差分数组常规操作
			update2(l,d*(l-1)); // 这里的 i(要修改的地方) 就是 l ,乘上 i-1 也就是 l-1 
			update2(r+1,-d*r); // 同理,乘上 i-1 也就是乘上 r+1-1 -> r 
		}
		else {
			cin>>l>>r;
//			cout<<r*sum1(r)<<' '<<sum2(r)<<' '<<(l-1)*sum1(l-1)<<" "<<sum2(l-1)<<endl;
			cout<<r*sum1(r)-sum2(r)-(l-1)*sum1(l-1)+sum2(l-1)<<endl;
		}
	}
	return 0;
}
2023/1/15 14:00
加载中...