//题意:一个数列,每次操作可以是将某区间数字都加上一个相同的整数,也可以是询问一个区间中所有数字的和。
//(这里区间指的是数列中连续的若干个数)对每次询问给出结果。
//这么水的题都写挫了也是够了
//总之还是线段树写的不够好呀。。快学学。。。
//5点需要注意
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll __int64
#define maxn 500000
using namespace std;
ll x,y,z;
ll n,m;
ll a[maxn];
struct node
{
ll l,r,ad,v;/// v是这一点的值,ad是要加未加的数
}tree[maxn*5];
void pushup(ll root)
{
tree[root].v=tree[root*2].v+tree[root*2+1].v;
return ;
}
void build(ll root,ll left,ll right)
{
tree[root].l=left;
tree[root].r=right;
tree[root].ad=0;
if(left==right)
{
tree[root].v=a[left];
return;
}
ll mid=(left+right)>>1;
build(root*2,left,mid);
build(root*2+1,mid+1,right);
pushup(root);
return;
}
void pushdown(ll root)
{
if(tree[root].ad!=0) //这里加一个优化 (1)
{
tree[root*2].ad+=tree[root].ad;
tree[root*2+1].ad+=tree[root].ad;
tree[root*2].v+=tree[root].ad*(tree[2*root].r-tree[2*root].l+1); //直接更新子节点值 (2)
tree[root*2+1].v+=tree[root].ad*(tree[2*root+1].r-tree[root*2+1].l+1);
tree[root].ad=0; // 注意这里要归零 (3)
}
return;
}
ll query(ll left,ll right,ll root) //写成有返回值型的
{
ll ans=0;
if(tree[root].l>=left&&tree[root].r<=right)
{
ans=tree[root].v;
return ans;
}
pushdown(root);
if(tree[root].l>right||tree[root].r<left)
return 0;
ll mid=(tree[root].l+tree[root].r)>>1;
if(left<=mid)
ans+=query(left,right,root*2);
if(right>=mid)
ans+=query(left,right,root*2+1);//这么写才好 (4)
return ans;
}
void addone(ll left,ll right,ll root ,ll c)
{
if(tree[root].l>=left&&tree[root].r<=right)
{
tree[root].ad+=c;
tree[root].v+=c*(tree[root].r-tree[root].l+1);
return;
}
pushdown(root); //搞一次更新一次
ll mid=(tree[root].l+tree[root].r)>>1;
if(left<=mid)
addone(left,right,root*2,c);
if(right>mid)
addone(left,right,root*2+1,c);
pushup(root); //因为改成直接更新value值,所以要pushup (5)
}
int main()
{
// freopen("3468.txt","r",stdin);
while(scanf("%I64d%I64d",&n,&m)!=EOF)
{
for(ll i=1;i<=n;i++)
scanf("%I64d",&a[i]);
build(1,1,n);
char s[5];
while(m--)
{
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%I64d%I64d",&x,&y);
ll ans=query(x,y,1);
printf("%I64d\n",ans);
}
else
{
scanf("%I64d%I64d%I64d",&x,&y,&z);
addone(x,y,1,z);
}
}
}
}
POJ 3468 线段树
最新推荐文章于 2018-08-25 10:45:11 发布
本文介绍了一个使用线段树实现区间加法和区间求和的问题解决方法。通过维护节点值和待加标签,优化了更新和查询操作。文章详细展示了线段树的建立、更新及查询过程。
286

被折叠的 条评论
为什么被折叠?



