luoguP2826 LJJ的数学课

思路

把公式拆开维护两个值,一个a[i]的总和,一个a[i]*i的总和
也可以用树状数组维护,模板题

代码

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#define ls rt<<1
#define rs rt<<1|1
#define ll long long
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn = 1e5 + 7;
int read() {
    int x = 0, f = 1; char s = getchar();
    for (; s < '0' || s > '9'; s = getchar()) if (s == '-') f = -1;
    for (; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
    return x * f;
}
int n,m,a[maxn];
struct node {
	int l,r,size;
	ll sum1,sum2;
}e[maxn<<2];
void pushup(int rt) {
	e[rt].sum1=e[ls].sum1+e[rs].sum1;
	e[rt].sum2=e[ls].sum2+e[rs].sum2;
}
void build(int l,int r,int rt) {
	e[rt].l=l,e[rt].r=r,e[rt].size=r-l+1;
	if(l==r) {
		e[rt].sum1=a[l];
		e[rt].sum2=a[l]*l;
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls);
	build(mid+1,r,rs);
	pushup(rt);
}
void modfity(int L,int k,int rt) {
	if(e[rt].l==e[rt].r) {
		e[rt].sum1+=k;
		e[rt].sum2=e[rt].sum1*L;
		return;
	}
	int mid=(e[rt].l+e[rt].r)>>1;
	if(L<=mid) modfity(L,k,ls);
	else modfity(L,k,rs);
	pushup(rt);
}
ll query_1(int L,int R,int rt) {
	if(L<=e[rt].l&&e[rt].r<=R) {
		return e[rt].sum1;
	}
	int mid=(e[rt].l+e[rt].r)>>1;
	ll ans=0;
	if(L<=mid) ans+=query_1(L,R,ls);
	if(R>mid) ans+=query_1(L,R,rs);
	return ans;
}
ll query_2(int L,int R,int rt) {
	if(L<=e[rt].l&&e[rt].r<=R) {
		return e[rt].sum2;
	}
	int mid=(e[rt].l+e[rt].r)>>1;
	ll ans=0;
	if(L<=mid) ans+=query_2(L,R,ls);
	if(R>mid) ans+=query_2(L,R,rs);
	return ans;	
}
int main() {
	n=read(),m=read();
	FOR(i,1,n) a[i]=read();
	build(1,n,1);
	FOR(i,1,m) {
		int k=read(),x=read(),y=read();
		if(k==1) {
			modfity(x,y,1);
		} else {
			ll ans=query_1(x,y,1)*(y+1)-query_2(x,y,1);
			printf("%lld
",ans);
		}
	}
	return 0;
}

原文地址:https://www.cnblogs.com/dsrdsr/p/9875740.html