POJ3468 —— 线段树 || 树状数组

A Simple Problem with Integers
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 49696   Accepted: 14708
Case Time Limit: 2000MS

Description

You have N integers, A1A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.

Source

POJ Monthly--2007.11.25, Yang Yi

题意是给你一个数列,有两种操作:1。C a b c 把区间a到b的每个元素都加上c ;2。Q a b 输出区间a到b的和

思路:1.线段树,要是用线段树做的话这个就是裸的区间修改+区间查询 , 维护区间和即可。

2.树状数组,这种属于一类比较巧妙的树状数组。

我们开两个树状数组,bit0 , bit1;我们设a数组从i到j的和 = bit0的前i项和  * i + bit1的前i项和。

那么我们把区间(l , r)加上add可以等效为:

1.在bit0的l上加- x * (l - 1);

2.在bit1的l上加x;

3.在bit0的r + 1上加x * r;

4.在bit1的r + 1上加- x;

这样就可以用树状数组了。PS:注意要用long long 

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
using namespace std;
///#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a))
#define lson l , mid  , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define mk make_pair
#define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)
#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)
#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)
#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)
const int MAXN = 100000 + 5;
const int MAXS = 10000 + 50;
const int sigma_size = 26;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
const int inf = 1 << 30;
#define eps 1e-8
const long long MOD = 1000000000 + 7;
const int mod = 100000;
typedef long long LL;
const double PI = acos(-1.0);
typedef double D;
typedef pair<int , int> pii;
#define Bug(s) cout << "s = " << s << endl;
///#pragma comment(linker, "/STACK:102400000,102400000")
int n , q , a[MAXN] ;
LL bit0[MAXN] , bit1[MAXN];
LL lowbit(int x){return x & (-x);}
void update(LL *c , int x , int add)
{
    while(x <= MAXN)
    {
        c[x] += add;
        x += lowbit(x);
    }
}
LL getsum(LL *c , int x)
{
    LL sum = 0 ;
    while(x > 0)///不能有等于零的情况
    {
        sum += c[x];
        x -= lowbit(x);
    }
    return sum;
}
int main()
{
    while(~scanf("%d%d" , &n , &q))
    {
        clr(bit0 ,0) , clr(bit1 , 0);
        for(int i = 1  ; i <= n ; i++)
        {
            scanf("%d" , &a[i]);
//            outstars
            update(bit0 , i , a[i]);
        }
        char cmd[5];
//        outstars

        for(int i = 0  ; i < q ; i++)
        {
//            Bug(q)
//            getchar();
            int a , b , c;
            scanf("%s%d%d" , cmd  , &a , &b);

//            Bug(cmd)
//            outstars
            if(cmd[0] == 'C')
            {
//                int a , b , c;
                scanf("%d" , &c);
                update(bit0 , a , (-c) * (a - 1));
                update(bit1 , a , c);
                update(bit0 , b + 1 , b * c);
                update(bit1 , b + 1 , -c);
            }
            else
            {
//                int a , b;
//                scanf("%d%d" , &a ,&b);
//                outstars
                LL ans = 0;
//                Bug(getsum(bit0 , b));
                ans += getsum(bit0 , b) + getsum(bit1 , b) * b;
//                cout << "999" << ' ' << endl;
                ans -= getsum(bit0 , a - 1) + getsum(bit1 , a - 1) * (a - 1);
                printf("%lld\n" , ans);
            }

//            outstars
        }
    }

    return 0;
}


你可能感兴趣的:(线段树,ACM,树状数组)