|
思路: 每个节点记录两个值: 所有子节点的增量和 该节点的增量 代码烂,1500+ms。 为了避免爆栈,实现计算好了左右边界和中间值。
#include <stdio.h>
#include <stdlib.h>

#define MAX_N 100032

int N;
 struct {
__int64 up, down;
int rl, rr, rm;
} tree[MAX_N*4];


 enum OP {
INSERT,
SUM,
} op;

__int64 val;

void tree_op(int idx, int l, int r)
  {
 if (op == INSERT) {
 if (tree[idx].rl == l && tree[idx].rr == r) {
tree[idx].up += val;
return ;
}
tree[idx].down += val * (r - l + 1);
 } else {
val += tree[idx].up * (r - l + 1);
 if (tree[idx].rl == l && tree[idx].rr == r) {
val += tree[idx].down;
return ;
}
}

 if (r <= tree[idx].rm) {
// all in left
tree_op(idx*2, l, r);
 } else if (l > tree[idx].rm) {
// all in right
tree_op(idx*2+1, l, r);
 } else {
// in left and right
tree_op(idx*2, l, tree[idx].rm);
tree_op(idx*2+1, tree[idx].rm + 1, r);
}
}

int main()
  {
int i, j, q;
char str[16];

freopen("e:\\test\\in.txt", "r", stdin);

tree[1].rl = 1;
tree[1].rm = (MAX_N + 1) / 2;
tree[1].rr = MAX_N;
 for (i = 2; i < _countof(tree); i++) {
 if (i & 1) {
tree[i].rl = tree[i/2].rm + 1;
tree[i].rr = tree[i/2].rr;
 } else {
tree[i].rl = tree[i/2].rl;
tree[i].rr = tree[i/2].rm;
}
tree[i].rm = (tree[i].rl + tree[i].rr) / 2;
}

scanf("%d%d", &N, &q);
op = INSERT;
 for (i = 1; i <= N; i++) {
scanf("%I64d", &val);
tree_op(1, i, i);
}

 while (q--) {
scanf("%s%d%d", str, &i, &j);
 if (str[0] == 'Q') {
val = 0;
op = SUM;
tree_op(1, i, j);
printf("%I64d\n", val);
 } else {
scanf("%I64d", &val);
op = INSERT;
tree_op(1, i, j);
}
}

return 0;
}

|