这一题,暴力的方法超时。只能用线段树来求解。
对于线段树,只是初学,还不是很懂,看了大神的博客,慢慢敲出来的。
关键还是那些递归的过程。递归的过程,也是理解了大概,也很难讲清楚递归的过程。
下面的是AC的代码:
# include <iostream>
# include <cstring>
# include <cstdio>
using namespace std;
const int N = 50005;
class Node
{
public:
int l, r;
__int64 sum;
};
Node tree[N * 3];
void creat_tree(int l, int r, int pos) //构造树状数组,递归构树
{
tree[pos].l = l;
tree[pos].r = r;
if(r == l)
{
scanf("%I64d", &tree[pos].sum); //叶子结点,输入
return;
}
int mid = (l + r) / 2;
creat_tree(l, mid, 2 * pos);
creat_tree(mid + 1, r, 2 * pos + 1);
tree[pos].sum = tree[pos * 2].sum + tree[pos * 2 + 1].sum;
}
void update(int k, int pos, int add) //更新各个结点的sum
{
if(k >= tree[pos].l && k <= tree[pos].r)
{
tree[pos].sum += add;
if(tree[pos].r == tree[pos].l) //叶子结点
return;
update(k, pos * 2, add);
update(k, pos * 2 + 1, add);
}
return;
}
__int64 Query(int l, int r, int pos) //计算区间l到r直接的sum和,不断的缩小范围来求解
{
if(l == tree[pos].l && r == tree[pos].r) //区间等于某个结点的区间,返回该结点的sum
{
return tree[pos].sum;
}
else if(r <= (tree[pos].l + tree[pos].r) / 2)
{
return Query(l, r, pos * 2);
}
else if(l >= (tree[pos].l + tree[pos].r) / 2 + 1)
{
return Query(l, r, pos * 2 + 1);
}
else
{
return Query(l, tree[pos * 2].r, pos * 2) + Query(tree[pos * 2 + 1].l, r, pos * 2 + 1);
}
}
int main()
{
// freopen("data.txt", "r", stdin);
int t;
int count = 1;
scanf("%d", &t);
while(t--)
{
int n;
scanf("%d", &n);
creat_tree(1, n, 1);
printf("Case %d:\n", count++);
char str[10];
while(1)
{
scanf("%s", str);
if(str[0] == 'E') //结束标志
{
break;
}
if(str[0] == 'A') //增加
{
int i, j;
scanf("%d%d", &i, &j);
update(i, 1, j);
}
else if(str[0] == 'S') //减少
{
int i, j;
scanf("%d%d", &i, &j);
update(i, 1, -j);
}
else if(str[0] == 'Q') //统计
{
int i, j;
scanf("%d%d", &i, &j);
printf("%I64d\n", Query(i, j, 1));
}
getchar();
}
}
return 0;
}