/* 线段树第三天,一天一道线段树坚持下去你就是高手*/
/* 终于把一些简单的线段树理解了,明白了 lazy 标记的好处
这是第三天了*/
#include<cstdio>
#include<iostream>
using namespace std;
#define _ long long
#define lson id<<1
#define rson id<<1|1
const _ Max = 500005;
struct line
{
_ left,right;
_ sum,mark;;
_ mid()
{
return (left + right) / 2;
}
}node[Max];
_ a[Max];
void PushUp(_ id)
{
node[id].sum = (node[lson].sum + node[rson].sum);
}
void Pushdown(_ id) // 传递 标记
{
if(node[id].mark)
{
node[lson].mark += node[id].mark; // 向下传递标记
node[rson].mark += node[id].mark;
node[lson].sum += (node[lson].right-node[lson].left + 1) * node[id].mark;
node[rson].sum += (node[rson].right-node[rson].left + 1) * node[id].mark;
node[id].mark = 0;
}
}
void _Build_Tree(_ id,_ l,_ r)
{
node[id].left = l,node[id].right = r;
node[id].mark = 0;
if(l == r)
{
node[id].sum = a[r];return;
}
_ mid = node[id].mid();
_Build_Tree(lson,l,mid);
_Build_Tree(rson,mid+1,r);
PushUp(id);
}
_ n;
void upside(_ l,_ r,_ c,_ id)
{
if(node[id].left == l && node[id].right ==r)
{
node[id].mark += c;
node[id].sum += (r - l + 1) * c;
return ;
}
_ mid = node[id].mid();
Pushdown(id);
if(l > mid)upside(l,r,c,rson);
else if(r<=mid)upside(l,r,c,lson);
else {
upside(l,mid,c,lson);
upside(mid+1,r,c,rson);
}
PushUp(id);
}
_ sum;
_ seach(_ id,_ l,_ r)
{
if(l==node[id].left&&r == node[id].right)
{
return node[id].sum;
}
Pushdown(id);
_ mid = node[id].mid();
if(r <= mid)return seach(lson,l,r);
else if(l>mid)return seach(rson,l,r);
else{
return seach(lson,l,mid) + seach(rson,mid+1,r);
}
}
int main()
{
_ n,m;
_ T,l,r,c,cn = 0;
char s[19];
while(~scanf("%lld%lld",&n,&m))
{
for(_ i=1;i<=n;i++)
scanf("%lld",&a[i]);
_Build_Tree(1,1,n);
while(m--)
{
scanf("%s",s);
if(s[0] == 'Q')
{ sum = 0;
scanf("%lld%lld",&l,&r);
printf("%lld\n",seach(1,l,r));
}
else{
scanf("%lld %lld %lld",&l,&r,&c);
upside(l,r,c,1);
}
}
}
}
PKU 3468 线段树,线段树 第 3 天
最新推荐文章于 2021-02-27 12:08:25 发布