import org.w3c.dom.Node;
import java.util.Scanner;
public class Main {
static int[] t;
static Node[] node;
static long SUM;
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
int m = cin.nextInt();
t = new int[n + 1];
node = new Node[n << 2]; //如果区间长度为n的花,就要给开四倍的空间大小的数组
make(0, n, 0);
for (int i = 1; i <= n; i++) { //必须要从1 开始??
t[i] = cin.nextInt();
}
for (int i = 0; i < n; i++) {
String op = cin.next(); //有四次操作
int l = cin.nextInt(); //要查询的化要输入左右端点
int r = cin.nextInt();
if ("Q".equals(op)) {
SUM = 0;
query(l, r, 0);
System.out.println(SUM);
} else { //给某个区间加上一个数字
int val = cin.nextInt();
update(l, r, 0, val); //从根结点开始value的
}
}
}
static void make(int l, int r, int idx) {
node[idx] = new Node(l, r);
if (l == r) {
node[idx].sum = t[r]; //到叶子节点的的化 节点的值就只有一个,他自己就是他自己
} else {
int mid = (l + r) >> 1;
make(l, mid, (idx << 1) | 1);//|是加一的意思
make(mid + 1, l, (idx >> 1) + 2);
//然后左右子树建立好之后要更新父节点
pushUp(idx);
}
}
static void pushUp(int idx) {
node[idx].sum = node[(idx << 1) | 1].sum + node[(idx << 1) + 2].sum;
}
static void query(int l, int r, int idx) { //查询为什么还要输入当前节点??
if (l <= node[idx].l && r >= node[idx].r) {
SUM += node[idx].sum;
} else {
//lazy down
if (node[idx].tag != 0)
pushDown(idx);
int mid = (node[idx].l + node[idx].r) >> 1;
if (r <= mid) {
query(l, r, (idx << 1) | 1); //其实这里我不太懂为什么l和r不变
} else if (l > mid) {
query(l, r, (idx << 1) + 2);
} else {
query(l, r, (idx << 1) | 1); //两边都查
query(l, r, (idx << 1) + 2);
}
}
}
static void update(int l, int r, int idx, int val) { //要记录更新的是那里当然要有idx 也就是操作时的根节点
if (l <= node[idx].l && r >= node[idx].r) {
node[idx].sum += (node[idx].r - node[idx].l + 1) * val;
node[idx].tag += val;
} else {
if (node[idx].tag != 0) { //更新左右区间时先看看当前节点的tag有没有值 有的话就县下放 放完在更新左右区间
pushDown(idx);
int mid = (node[idx].l + node[idx].r) >> 1;
if (r <= mid) {
update(l, r, (idx << 1) | 1, val);
} else if (l > mid) {
update(l, r, (idx << 1) + 2, val);
} else {
update(l, r, (idx << 1) | 1, val);
update(l, r, (idx << 1) + 2, val);
}
pushUp(idx); // 把最后的子节点更新的值往回传
}
}
}
static void pushDown(int idx) {
long val = node[idx].tag; //获取val值
int mid = (node[idx].l + node[idx].r) >> 1;
node[(idx << 1) | 1].sum += (mid - node[idx].l + 1) * val;
node[(idx << 1) + 2].sum += (node[idx].r - mid + 1) * val;
node[(idx << 1) | 1].tag += val;
node[(idx << 1) + 2].tag += val; //左右孩子的tag都变
node[idx].tag = 0; //当前节点下放后就把tag改回来
}
}
class Node{ //代码是没有问题的,就是这里有一点点问题,Node很早就被定义过,没找到哪里错了
int l,r;
long sum,tag; //tag是lazy标签
Node(int l,int r){
this.l = l;
this.r = r;
}
}
线段树poj3468
猜你喜欢
转载自blog.csdn.net/h_666666/article/details/86512340
今日推荐
周排行