#include<iostream> #include<algorithm> #include<stdio.h> using namespace std; #define Lson rt<<1 #define Rson rt<<1|1 //这里写的和学长不一样,我遵从是叶子结点的四倍定义数组,学长定义的是 1e5+5<<1, const int Maxn=1e5+5; struct node { int mid, len, L, R; __int64 e, sum; } a[Maxn<<2];//第一次提交runtime了,我发现是数组开小了,我发现我定义的是叶子结点的二倍,粗心了。 //不过还是基础知识不牢固,毕竟我只是记住了结论,但不知从何而推来。 __int64 x; void Buildsegtree(int rt, int L, int R);//建立 void pushdown(int rt);//下推 __int64 Query(int rt, int L, int R);//查询 void Update(int rt, int L, int R, int e);//更新 int main() { int n, m, a, b, c; scanf("%d%d", &n, &m); Buildsegtree(1, 1, n); while(m--) { char s[3]; scanf("%s", s); if(s[0]=='Q') { scanf("%d%d", &a, &b); printf("%I64d ", Query(1, a, b)); } else { scanf("%d%d%d", &a, &b, &c); Update(1, a, b, c); } } return 0; } void Buildsegtree(int rt, int L, int R)//建立 { a[rt].L=L; a[rt].R=R; a[rt].e=0;//这点没写,之后核对的时候才发现 a[rt].mid=(L+R)>>1; a[rt].len=(R-L)+1;//我吧if语句写在了这些赋值语句之前,不知道可以不, //反正改了过来,不过我觉得写前面后面都一样,毕竟它的叶子节点没有左孩子和有孩子了 //之后把他俩换了换位置发现不行 if(L==R) { scanf("%I64d", &x); a[rt].sum=x; return; } Buildsegtree(Lson, L, a[rt].mid); Buildsegtree(Rson, a[rt].mid+1, R); a[rt].sum=a[Lson].sum+a[Rson].sum; } void pushdown(int rt)//下推 { a[Lson].sum+=a[rt].e*a[Lson].len; a[Lson].e+=a[rt].e; a[Rson].sum+=a[rt].e*a[Rson].len; a[Rson].e+=a[rt].e; a[rt].e=0; } __int64 Query(int rt, int L, int R) { if(a[rt].L==L&&a[rt].R==R) { return a[rt].sum; } pushdown(rt); if(R<=a[rt].mid) Query(Lson, L, R); else if(L>a[rt].mid) Query(Rson, L, R); else { __int64 Lsum=Query(Lson, L, a[rt].mid); __int64 Rsum=Query(Rson, a[rt].mid+1, R); return Lsum+Rsum; } } void Update(int rt, int L, int R, int e) { //少写了这一步 a[rt].sum+=(R-L+1)*e; if(a[rt].L==L&&a[rt].R==R) { a[rt].e+=e; return; } pushdown(rt); if(R<=a[rt].mid) Update(Lson, L, R, e); else if(L>a[rt].mid) Update(Rson, L, R, e); else { Update(Lson, L, a[rt].mid, e); Update(Rson, a[rt].mid+1, R, e); } }