徐州网络赛 Ryuji doesn't want to study [树状数组]

传送门

树状数组,一个树状数组会T, 采用两个树状数组。

一个存a[1] + a[2] + a[3] + ... a[n -1] + a[n] ;

另一个存n * a[1] + (n-1) * a[2] + (n-2) * a[3] +... 2 * a[n-1] + a[n] ;

ans1 = getsum1(r) - getsum1(l-1)   // a[l] + a[l + 1] + ... a[r];

ans2 = getsum2(r) - getsum(l-1) //  (n - l + 1) * a[l] + (n - l) *a[l + 1] + ... (n-r+1) * a[r]; 

ans = ans2 - (n - r) * ans1;  // n - r 自己去推一下

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int MaxN = 1e5 + 5;
long long a1[MaxN], a2[MaxN];
int n, q, m;

int lowbit(int x) {
	return x & (-x);
}

void update1(int x, long long val) {
	for(int i = x; i <= n; i += lowbit(i)) 
		a1[i] += val;
}

void update2(int x, long long val) {
	for(int i = x; i <= n; i += lowbit(i)) {
		a2[i] += val;
	}
}

long long getsum1(int x) {
	long long ans = 0;
	for(int i = x; i > 0; i -= lowbit(i)) 
		ans += a1[i];
	return ans;
}

long long getsum2(int x) {
	long long ans = 0;
	for(int i = x; i > 0; i -= lowbit(i))
		ans += a2[i];
	return ans;
}

int main() {
	scanf("%d %d", &n, &q);
	for(int i = 1; i <= n; i++) {
		long long pp;
		scanf("%lld", &pp);
		update1(i, pp);
		update2(i, pp * (n-i+1));
	}
	//for(int i = 1; i <= n; i++) printf("%lld %lld\n", a1[i], a2[i]);
	while(q--) {
		int op, l, r;
		scanf("%d%d%d", &op, &l, &r);
		if(op == 1) {
			long long ans1 = getsum2(r) - getsum2(l-1);
			long long ans2 = getsum1(r) - getsum1(l-1);
			long long ans = ans1 - (n-r) * ans2;
			printf("%lld\n", ans);
		}
		else {
			long long tem = getsum1(l) - getsum1(l-1);
			update1(l, r - tem);
			update2(l, (r - tem) * (n-l+1));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40844130/article/details/82633391