poj 3468 A Simple Problem with Integers

poj 3468 A Simple Problem with Integers  用两个数组数组

题意:给出n个数,然后进行q次处理,a b表示求出区间【a, b】的和, C a b c表示把区间[a, b]里的数都加上c。

刚开始更新[a, b]区间里的数时,用了一个循环对区间内的每个点都更新一次,超时了


思路:

假设frist[i]表示原来第i个数的值, change[i]表示区间[i, n]所改变的值, 如[i , n]变化d就是 change[i] += d。

则区间[1, n]的和为

ans = first[1] + first[2] + .... + first[n] + chang[1] * (n) + chang[2] * (n - 1) +.....+chang[n]

                = sum(n) + (x + 1) * sum(chang[i]) - sum(chang[i] * i)                      1 <= i <= n

chang[i] * (n + 1 - i)表示有(n + 1 - i)个数增加了chang[i](正数或负数)

      则区间[L, R]的和为

s(L - 1) = first[1] + first[2] + .... + first[L - 1] + chang[1] * (L - 1) + chang[2] * (L - 1) +.....+chang[L]

                = sum(L - 1) + (L - 1 + 1) * sum(chang[i]) - sum(chang[i] * i)                      1 <= i <= L - 1

sR = first[1] + first[2] + .... + first[R] + chang[1] * (R) + chang[2] * (R - 1) +.....+chang[R]

                = sum(R) + (R + 1) * sum(chang[i]) - sum(chang[i] * i)                      1 <= i <= R

[L, R]的和为sR -s(L - 1)。

sum(chang[i]), sum(chang[i] * i)求法:使用树状数组,一个表示chang[i], 另一个表示chang[i]*i。

用long long int


下面是自己的代码

#include <stdio.h>
#include <string.h>
#define maxn 100010
long long int sum[maxn], a[maxn], b[maxn];
long long int n, q;
long long int lowbit(long long int x)
{
	return x & (-x);
} 

void update(long long int x, long long int num, long long int c[])
{
	while(x <= n)
	{
		c[x] += num;
		x += lowbit(x);
	}
}

long long int getSum(long long int x, long long int c[])
{
	long long int s = 0;
	while(x > 0)
	{
		s += c[x];
		x -= lowbit(x);
	}
	return s;
}

int main()
{
	char ask[3];
	int i, l, r, add, num;
	long long int ans, sl, sr;
	
	scanf("%d %d", &n, &q);
	{
		for(i = 1;i <= n;i++)
		{
			scanf("%d", &num);
			sum[i] = sum[i - 1] + num;
		} 
		
		for(i = 0;i < q;i++)
		{
			scanf("%s", ask);
			if(strcmp(ask, "Q") == 0)
			{
				scanf("%d %d", &l, &r);
				sl = sum[l - 1] + (l + 1 - 1) * getSum(l - 1, a) - getSum(l - 1, b);
				sr = sum[r] + (r + 1) * getSum(r, a) - getSum(r, b);
				ans = sr - sl;
				printf("%lld\n", ans);
			}
			else if(strcmp(ask, "C") == 0)
			{
				scanf("%d %d %d", &l, &r, &add);
				
				update(l, add, a);
				update(r+1, -add, a);
				update(l, add*l, b);
				update(r+1, -add*(r+1), b);
			}
		}
	}
	return 0;
} 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值