poj 3468 A Simple Problem with Integers 用两个数组数组
题意:给出n个数,然后进行q次处理,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;
}