索引:
(一)树状数组:
a代表原始数组,c代表树状数组,n很重要!!!!
(1)在多种情况下,树状数组要初始化:void init();
(2)求最低位:int lowbit(int x);
(3)单点更新:void update(int x,int y);
(4)前x项求和:int getsum(int x);

(二)线段树
a代表原始数组,segtree代表线段树结构体
(1)建线段树,相当于初始化:void build(int l,int r,int rt);
(2)单点更新:void update(int L,int C,int l,int r,int rt);
(3)区间求和:int query(int L,int R,int l,int r,int rt);
(4)下推   :void pushdown(int rt,int ln,int rn);  //用于区间更新
(5)区间更新:void qujian_update(int L,int R,int C,int l,int r,int rt);
(6)区间更新的区间查询:void qujian_update(int L,int R,int C,int l,int r,int rt);
树状数组:
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
using namespace std;
typedef long long ll;

int a[50005]; //原数组
int c[50005]; //树状数组

void init() //初始化a,c数组
{
    memset(a, 0, sizeof(a));
    memset(c, 0, sizeof(c));
}

int n; //一共多少个兵营

int lowbit(int x)
{
    return x&(-x);
}

void updata(int i,int k) //在i位置加上k,并更新数组的数据
{
    while(i<=n) 
    {
        c[i]+=k;
        i+=lowbit(i);
    }
}

int getsum(int i) //求前i项的和
{
    int ans=0;
    while(i>0)
    {
        ans+=c[i];
        i-=lowbit(i);
    }
    return ans;
}



线段树:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
const int maxn = 50005;
int T,n;
int a[maxn];
string s;
struct sss
{
    int val,lazy;
}SegTree[maxn<<2];

void build(int l,int r,int rt)
{
    SegTree[rt].lazy = 0;
    if(l==r)
    {
        SegTree[rt].val = a[l];
        return;
    }
    int mid = (l+r)/2;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    SegTree[rt].val = SegTree[rt<<1].val + SegTree[rt<<1|1].val; //回溯方法
}

void update(int L,int C,int l,int r,int rt)
{
    if(l==r)
    {
        SegTree[rt].val += C;  //这里是rt的val+=C,不是l或r的
        return;
    }
    int mid = (l+r) >> 1 ;
    if(L <= mid) update(L, C, l, mid, rt<<1);
    else         update(L, C, mid+1, r, rt<<1|1);
    SegTree[rt].val = SegTree[rt<<1].val + SegTree[rt<<1|1].val;
}


void pushdown(int rt,int ln,int rn)
{
    if(SegTree[rt].lazy)
    {
        SegTree[rt<<1].lazy += SegTree[rt].lazy;
        SegTree[rt<<1|1].lazy += SegTree[rt].lazy;
        SegTree[rt<<1].val += SegTree[rt].lazy * ln;
        SegTree[rt<<1|1].val += SegTree[rt].lazy *rn;
        SegTree[rt].lazy = 0;
    }
}
void qujian_update(int L,int R,int C,int l,int r,int rt)
{
    if(l>=L && r<=R) //只有[l,r]全部在[L,R]区间内才可以更新,直到是叶子节点
    {
        SegTree[rt].val += C * (r-l+1);
        SegTree[rt].lazy += C;
        return;
    }
    int mid = (l+r) >> 1;
    pushdown(rt,mid-l+1,r-mid);
    if(L<=mid) qujian_update(L, R, C, l, mid, rt<<1);
    if(R>mid)  qujian_update(L, R, C, mid+1 ,r, rt<<1|1);
    SegTree[rt].val = SegTree[rt<<1].val + SegTree[rt<<1|1].val;
}

int query(int L,int R,int l,int r,int rt)
{
    if(l>=L && r<=R) return SegTree[rt].val;
    if(l>R || r<L) return 0;
    int mid = (l+r)>>1;
    return query(L, R, l, mid, rt<<1) + query(L, R, mid+1, r, rt<<1|1);
}

int qujian_query(int L,int R,int l,int r,int rt)
{
    if(l>=L && r<=R) return SegTree[rt].val;
    if(l>R || r<L) return 0;
    int mid = (l+r)>>1;
    pushdown(rt, mid-l+1, r-mid);
    return qujian_query(L, R, l, mid, rt<<1) + qujian_query(L, R, mid+1, r, rt<<1|1);
}

int main()
{
    scanf("%d",&T);
    for (int I=1;I<=T;I++)
    {
        cout << "Case " << I << ":" << endl;
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        build(1, n, 1); //相当于初始化,不用像树状数组单独初始化了
        while(cin >> s)
        {
            int x,y;
            if(s=="End") break;
            else
            {
                scanf("%d %d",&x,&y);
                if(s=="Add") update(x, y, 1, n, 1);
                if(s=="Sub") update(x, -y, 1, n, 1);
                if(s=="Query") cout << query(x, y, 1, n, 1) << endl;
            }
        }
    }
    return 0;
}