poj 3468 (一个关于整数的问题)

这题本来准备想暴力A过去,但是超时了,好吧 抓狂。想想还是用线段树来做吧,期间我借鉴了树状数组的代码。。。
#include <stdio.h>
#include <stdlib.h>

#define MAX_N	100000

long long data_mul[MAX_N];
long long data_add[MAX_N];

void internal_update(int at, long long mul, long long add) {
	int i;
	for(i = at; i < MAX_N; i = (i | (i + 1))) {
		data_mul[i] += mul;
		data_add[i] += add;
	}
}

void update(int left, int right, long long it) {
	internal_update(left, it, -it * (left - 1));
	internal_update(right, -it, it * right);
}

long long query_sum(int x) {
	long long mul = 0, add = 0;
	int start = x;
	int i;
	for(i = x; i >= 0; i = (i & (i + 1)) - 1) {
		mul += data_mul[i];
		add += data_add[i];
	}
	return mul * start + add;
}

long long query(int x, int y) {
	return query_sum(y) - query_sum(x - 1);
}

int main(int argc, char *argv[]) {
	int N, Q;
	int i;
	long long l;
	int a, b;
	long long c;
	char ch;
	scanf("%d %d", &N, &Q);
	for(i = 0; i < N; ++i) {
		scanf("%lld", &l);
		update(i, i, l);
	}
	while(Q--) {
		getchar();
		scanf("%c", &ch);
		if(ch == 'Q') {
			scanf("%d %d", &a, &b);
			printf("%lld\n", query(a-1, b-1));
		}
		else {
			scanf("%d %d %lld", &a, &b, &c);
			update(a-1, b-1, c);
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值