POJ3468树状数组

来源:互联网 发布:海关进口数据怎么查询 编辑:程序博客网 时间:2024/05/04 02:30

题目:题目链接

 

题意:

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.The second line contains N numbers,

the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.Each of the next Q lines

represents an operation."C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.

"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

就是区间更新,求区间总和sum,树状数组(或者线段树):

 

Sum[x] = SUM(A[i], i=1...x)+(x+1)*SUM(delta[i],i=1...x)-SUM(i*delta[i],i=1...x)在成段更新时,是对delta

数组进行更新,于是用两个树状数组t1,t2来维护两个前缀和SUM(delta[i],i=1...x),SUM(i*delta[i],i=1...x),而

SUM(A[i], i=1...x)在更新过程中是不变的,所以可以预处理在数组中将区间的成段更新转化成对t1,t2两个树状数

组的单点更新,使更新复杂度保持O(log(n))

#include <iostream>#include <cstdio>#include <string>#include <string.h>#include <map>#include <vector>#include <cstdlib>#include <algorithm>#include <cmath>#include <queue>#include <set>#include <stack>#include <functional>#include <fstream>#include <sstream>#include <iomanip>#include <numeric>#include <cassert>#include <bitset>#include <stack>#include <ctime>#include <list>#define INF 0x7fffffff#define max3(a,b,c) (max(a,b)>c?max(a,b):c)#define min3(a,b,c) (min(a,b)<c?min(a,b):c)#define mem(a,b) memset(a,b,sizeof(a))using namespace std;#define maxn 100005__int64 sum[maxn];__int64 t1[maxn];__int64 t2[maxn];inline __int64 lowbit(int x){    return (-x)&x;}inline void update(__int64 a[], int x, __int64 c){    while(x <= maxn)    {        a[x] += c;        x += lowbit(x);    }}inline __int64 getSum(__int64 a[], int x){    __int64 sum0 = 0;    while(x)    {        sum0 += a[x];        x -= lowbit(x);    }    return sum0;}//根据公式Sum[x] = SUM(A[i], i=1...x)+(x+1)*SUM(delta[i],i=1...x)-SUM(i*delta[i],i=1...x)求Sum[x]__int64 Sum(__int64 t1[], __int64 t2[], int x){    __int64 res = sum[x];    res += (x+1)*getSum(t1, x);    res -= getSum(t2, x);    return res;}int main(){    int  n, q, tmp;    mem(t1, 0);    mem(t2, 0);    scanf("%d%d", &n, &q);    for(int i = 1; i <= n; ++i)    {        scanf("%d", &tmp);        sum[i] = sum[i-1] + tmp;    }    while(q--)    {        __int64 suma, sumb;        char ch;        int a, b, c;        getchar();        scanf("%c", &ch);        if(ch == 'Q')        {            scanf("%d%d", &a, &b);            suma = Sum(t1, t2, a-1);            sumb = Sum(t1, t2, b);            printf("%I64d\n", sumb - suma);        }        else        {            scanf("%d%d%d", &a, &b, &c);            update(t1, a, c);//更新SUM(delta[i],i=1...x)中的delta[a]              update(t2, a, a*c);//更新SUM(i*delta[i],i=1...x)中的delta[a]              //这两个update后,区间A[a...n]每个数都增加了c。              update(t1, b+1, -c);//这两个update后,区间A[b+1...n]每个数都减少了c,完成对区间A[a...b]的更新              update(t2, b+1, -(b+1)*c);        }    }    return 0;}


 

 还是要学习线段树/树状数组.....

原创粉丝点击