这是线段树带区间更新的模版,用结构体实现的。 LightOJ - 1112 Curious Robin Hood [interval tree] 这个题线段树的实现方法是用区间去推节点位置,感觉两个的理解难度都差不多。
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<iomanip>
#include<string>
#include<climits>
#include<cmath>
#define MAX 110000
#define LL long long
using namespace std;
LL n,m;
LL ans;
struct Tree
{
LL l,r;
LL sum,add;
};
Tree tree[MAX*
3];
void pushup(LL x)
{
LL tmp=
2*x;
tree[x].sum=tree[tmp].sum+tree[tmp+
1].sum;
}
void pushdown(LL x)
{
LL tmp=
2*x;
tree[tmp].add += tree[x].add;
tree[tmp+
1].add += tree[x].add;
tree[tmp].sum += tree[x].add*(tree[tmp].r-tree[tmp].l+
1);
tree[tmp+
1].sum += tree[x].add*(tree[tmp+
1].r-tree[tmp+
1].l+
1);
tree[x].add=
0;
}
void build(
int l,
int r,
int x)
{
tree[x].l=l;
tree[x].r=r;
tree[x].add=
0;
if(l==r)
{
scanf(
"%lld",&tree[x].sum);
return ;
}
int tmp=x<<
1;
int mid=(l+r)>>
1;
build(l,mid,tmp) ;
build(mid+
1,r,tmp+
1);
pushup(x);
}
void update(LL l,LL r,LL c,LL x)
{
if(r<tree[x].l||l>tree[x].r)
return ;
if(l<=tree[x].l&&r>=tree[x].r)
{
tree[x].add+=c;
tree[x].sum+=c*(tree[x].r-tree[x].l+
1);
return ;
}
if(tree[x].add)
pushdown(x);
LL tmp=x<<
1;
update(l,r,c,tmp);
update(l,r,c,tmp+
1);
pushup(x);
}
void query(LL l,LL r,LL x)
{
if(r<tree[x].l||l>tree[x].r)
return ;
if(l<=tree[x].l&&r>=tree[x].r)
{
ans += tree[x].sum;
return ;
}
if(tree[x].add)
pushdown(x);
LL tmp=x<<
1;
LL mid=(tree[x].l+tree[x].r)>>
1;
if(r<=mid)
query(l,r,tmp);
else if(l>mid)
query(l,r,tmp+
1);
else
{
query(l,mid,tmp);
query(mid+
1,r,tmp+
1);
}
}
int main()
{
while(~
scanf(
"%lld %lld",&n,&m))
{
build(
1,n,
1);
char str[
5];
while(m--)
{
scanf(
"%s",str);
if(str[
0]==
'Q')
{
LL l,r;
scanf(
"%lld %lld",&l,&r);
ans=
0;
query(l,r,
1);
printf(
"%lld\n",ans);
}
else
{
LL l,r,c;
scanf(
"%lld %lld %lld",&l,&r,&c);
update(l,r,c,
1);
}
}
}
return 0;
}
转载请注明原文地址: https://ju.6miu.com/read-8055.html