传送门:点击打开链接
线段树入门题。
题目大意:
区间操作,有两种操作。
1:区间累加。
2:区间求和。
解题思路:
主要是加深对于延时标记的理解,一开始写了一下。但是没过样例,然后问实验室的学弟。他大概给我讲了一下啊。主要思路就是,对于一个区间来说,它一定要增加来自上方的标记,并且把自身的标记增加 向下传。额。。大概就是这样。
#include <cstdio>
#define maxn 100000
#define LL long long
struct Node
{
int l,r;
LL sum,c;
}tree[maxn<<2];
inline void pushup(int id)
{
tree[id].sum = tree[id<<1].sum + tree[id<<1|1].sum;
}
inline void pushdown(int id)
{
if(tree[id].c)
{
tree[id<<1].c += tree[id].c;
tree[id<<1|1].c += tree[id].c;
int len = tree[id].r-tree[id].l+1;
tree[id<<1].sum += (len-(len>>1))*(tree[id].c);
tree[id<<1|1].sum += (len>>1)*(tree[id].c);
tree[id].c = 0;
}
}
void build(int id,int l,int r)
{
tree[id].l = l;
tree[id].r = r;
tree[id].c = 0;
if(l == r)
{
int x;
scanf("%I64d",&x);
tree[id].sum = x;
return ;
}
int mid = (l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id);
}
LL query(int id,int l,int r)
{
if(tree[id].l >= l && tree[id].r <= r)
{
return tree[id].sum;
}
pushdown(id);
int mid = (tree[id].l + tree[id].r) >>1;
LL res = 0;
if(l <= mid) res += query(id<<1,l,r);
if(r > mid) res += query(id<<1|1,l,r);
return res;
}
void op(int id,int l,int r,LL c)
{
if(tree[id].l >= l && tree[id].r <= r)
{
tree[id].c += c;
tree[id].sum += c*(tree[id].r - tree[id].l+1);
return ;
}
pushdown(id);
int mid = (tree[id].l + tree[id].r )>>1;
if(l <= mid) op(id<<1,l,r,c);
if(r > mid) op(id<<1|1,l,r,c);
pushup(id);
}
int main()
{
int n,q;
while(scanf("%d %d",&n,&q) != EOF)
{
build(1,1,n);
//printf("%I64d\n",query(1,4,4));
while(q--)
{
char s[10];
scanf("%s",s);
if(s[0] == 'Q')
{
int l,r;
scanf("%d %d",&l,&r);
printf("%I64d\n",query(1,l,r));
}
else
{
int l,r;
LL c;
scanf("%d %d %I64d",&l,&r,&c);
op(1,l,r,c);
}
}
}
return 0;
}