本来准备下一阶段再看看线段树的,想了解一下Splay,但是匡斌的博客刚好以这个题为例讲Splay,然后就先用线段树写了这个题写了这个题...
题意:区间更新,区间求和.
分析:直接套模板吧,但是要注意数据范围,改用long long千万不要用int的哇.
参考代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int n,q;
int a[maxn];
struct Node{
int l,r;
ll sum;
ll add;
};
Node st[maxn<<2];
void PushUp( int rt)
{
st[rt].sum = st[rt<<1].sum+st[rt<<1|1].sum;
}
void Build( int l, int r, int rt)
{
st[rt].l = l;
st[rt].r = r;
st[rt].add = 0;
if( l == r)
{
st[rt].sum = a[l];
return;
}
int mid = (l+r)>>1;
Build(l,mid,rt<<1);
Build(mid+1,r,rt<<1|1);
PushUp(rt);
}
void PushDown( int rt)
{
if( st[rt].add)
{
// st[rt<<1].add += st[rt].add;
// st[rt<<1|1].add += st[rt].add;
// st[rt].add = 0;
st[rt<<1].sum += (st[rt<<1].r-st[rt<<1].l+1)*st[rt].add;
st[rt<<1|1].sum += (st[rt<<1|1].r-st[rt<<1|1].l+1)*st[rt].add;
st[rt<<1].add += st[rt].add;
st[rt<<1|1].add += st[rt].add;
st[rt].add = 0;
}
}
//查找区间L~R的和
ll Query( int L, int R, int rt)
{
if( L <= st[rt].l && R >= st[rt].r)//根节点rt的范围要在区间[L,R]之内的哇
{
return st[rt].sum;
}
PushDown(rt);
int mid = (st[rt].l+st[rt].r)>>1;
if( R <= mid)
return Query(L,R,rt<<1);
else if( L > mid)
return Query(L,R,rt<<1|1);
else
return Query(L,mid,rt<<1)+Query(mid+1,R,rt<<1|1);
}
void Update( int L, int R, int rt, int val)
{
if( L <= st[rt].l && R >= st[rt].r)
{
st[rt].sum += (st[rt].r-st[rt].l+1)*val;
st[rt].add += val;
return;
}
PushDown(rt);
int mid = (st[rt].l+st[rt].r)>>1;
if( R <= mid)
Update(L,R,rt<<1,val);
else if( L > mid)
Update(L,R,rt<<1|1,val);
else
{
Update(L,mid,rt<<1,val);
Update(mid+1,R,rt<<1|1,val);
}
PushUp(rt);
}
int main()
{
while( ~scanf("%d%d",&n,&q))
{
for( int i = 1; i <= n; i++)
scanf("%d",&a[i]);
Build(1,n,1);//建树
while( q--)
{
char str[10];
int l,r;
scanf("%s%d%d",str,&l,&r);
if( str[0] == 'Q')
{
ll ans = Query(l,r,1);
printf("%lld\n",ans);
}
else if( str[0] == 'C')
{
int val;
scanf("%d",&val);
Update(l,r,1,val);
}
}
}
return 0;
}