2018.10.22 cogs2471. [EZOI 2016]源氏的数学课(线段树)

本文深入探讨了线段树在解决特定类型问题时的应用技巧,包括如何将复杂表达式拆解为更简单的部分进行维护,提供了详细的代码实现,以及如何通过更新和查询操作来高效处理区间问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门
线段树入门操作。
直接把题目给的 ( r − i + 1 ) ∗ a [ i ] (r-i+1)*a[i] (ri+1)a[i]拆开变成 ( r + 1 ) ∗ 1 ∗ a [ i ] − i ∗ a [ i ] (r+1)*1*a[i]-i*a[i] (r+1)1a[i]ia[i]因此只需要维护 ∑ i = l r a [ i ] \sum _{i=l} ^r a[i] i=lra[i] ∑ i = l r i ∗ a [ i ] \sum _{i=l} ^r i*a[i] i=lria[i]就行了。
代码:

#include<bits/stdc++.h>
#define N 100005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define ll long long
using namespace std;
inline ll read(){
	ll ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
int n,m;
ll sum[N],a[N];
struct Node{int l,r;ll sum1,sum2;}T[N<<1];
inline void pushup(int p){T[p].sum1=T[lc].sum1+T[rc].sum1,T[p].sum2=T[lc].sum2+T[rc].sum2;}
inline void build(int p,int l,int r){
	T[p].l=l,T[p].r=r;
	if(l==r){T[p].sum1=a[l],T[p].sum2=T[p].l*a[l];return;}
	build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int k,ll v){
	if(T[p].l==T[p].r){
		T[p].sum1+=v;
		T[p].sum2+=T[p].l*v;
		return;
	}
	if(k<=mid)update(lc,k,v);
	else update(rc,k,v); 
	pushup(p);
}
inline pair<ll,ll>query(int p,int ql,int qr){
	if(ql<=T[p].l&&T[p].r<=qr)return make_pair(T[p].sum1,T[p].sum2);
	if(qr<=mid)return query(lc,ql,qr);
	if(ql>mid)return query(rc,ql,qr);
	pair<ll,ll>ret1=query(lc,ql,mid),ret2=query(rc,mid+1,qr);
	return make_pair(ret1.first+ret2.first,ret1.second+ret2.second);
}
int main(){
	freopen("overwatch.in","r",stdin);
	freopen("overwatch.out","w",stdout);
	n=read(),m=read();
	for(int i=1;i<=n;++i)sum[i]=sum[i-1]+i,a[i]=read();
	build(1,1,n);
	while(m--){
		int op=read(),x=read();
		if(op==1)update(1,x,read());
		else{
			int y=read();
			pair<ll,ll>ret=query(1,x,y);
			ll ans=ret.first*(y+1)-ret.second;
			printf("%lld\n",ans);
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值