//题意:一个数列,每次操作可以是将某区间数字都加上一个相同的整数,也可以是询问一个区间中所有数字的和。
//(这里区间指的是数列中连续的若干个数)对每次询问给出结果。
//这么水的题都写挫了也是够了
//总之还是线段树写的不够好呀。。快学学。。。
//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 线段树
最新推荐文章于 2017-07-20 20:35:50 发布