题目大意:给你一串数字,和一堆询问,分别是问一段区间的和,和给某段数字每个数字增加一定的值。
解题思路:用暴力做肯定会超时,所以用线段树或者树状数组都可以做。这里为了练习线段树就用线段树做了。
线段树的思路就是将当前区间二分成一颗二叉树,通过区间的合并和分解来实现对区间值的修改。
做出来的第一个线段树,纪念一下。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
__int64 n,q;
__int64 num[100100];
char c[10];
__int64 x,y,z,ans;
struct PPP
{
__int64 l,r,sum,lazy;
}tree[210000];
__int64 tail;
void build(__int64 k,__int64 s,__int64 t)
{
tree[k].lazy=0;
__int64 mid = (s+t)/2;
if (s == t) {
tree[k].sum = num[s];
return;
}
tail++;
tree[k].l = tail;
build(tail,s,mid);
tail++;
tree[k].r = tail;
build(tail,mid+1,t);
tree[k].sum = tree[tree[k].l].sum+tree[tree[k].r].sum;
return;
}
//求某一段数的和
__int64 find(__int64 s,__int64 t,__int64 k,__int64 ss,__int64 tt)
{
__int64 mid = (ss+tt)/2;
if (ss != tt) {
tree[tree[k].l].lazy += tree[k].lazy;
tree[tree[k].r].lazy += tree[k].lazy;
}
tree[k].sum += (tt-ss+1) * tree[k].lazy;
tree[k].lazy = 0;
if (s==ss&&t==tt) {
return tree[k].sum;
}
if (s>=mid+1){
return find(s,t,tree[k].r,mid+1,tt);
}
if (t<=mid) {
return find(s,t,tree[k].l,ss,mid);
}
return find(s,mid,tree[k].l,ss,mid)+find(mid+1,t,tree[k].r,mid+1,tt);
}
//改变某段数的值
void change(__int64 s,__int64 t,__int64 k,__int64 ss,__int64 tt,__int64 temp)
{
__int64 mid = (ss+tt)/2;
if (ss != tt) {
tree[tree[k].l].lazy += tree[k].lazy;
tree[tree[k].r].lazy += tree[k].lazy;
}
tree[k].sum += (tt-ss+1) * tree[k].lazy;
tree[k].lazy = 0;
if (s==ss&&t==tt) {
tree[k].lazy += temp;
return;
}
else {
tree[k].sum += (t-s+1) * temp;
}
if (s>=mid+1){
change(s,t,tree[k].r,mid+1,tt,temp);
return;
}
if (t<=mid) {
change(s,t,tree[k].l,ss,mid,temp);
return;
}
change(s,mid,tree[k].l,ss,mid,temp);
change(mid+1,t,tree[k].r,mid+1,tt,temp);
return;
}
//查找某一个数的值
void work(__int64 k,__int64 s,__int64 t)
{
__int64 mid = (s+t)/2;
if (s == t) {
//printf("!!!!%I64d %I64d\n",s,tree[k].sum+tree[k].lazy);
return;
}
work(tree[k].l,s,mid);
work(tree[k].r,mid+1,t);
}
int main()
{
scanf("%I64d%I64d",&n,&q);
for (__int64 i = 1; i <= n ; i ++)
scanf("%I64d",&num[i]);
tail = 1;
build(1,1,n);
for (__int64 i = 1 ; i <= q ; i ++)
{
scanf("%s",c);
if (c[0] == 'Q') {
scanf("%I64d%I64d",&x,&y);
ans = find(x,y,1,1,n);
printf("%I64d\n",ans);
}
if (c[0] == 'C') {
scanf("%I64d%I64d%I64d",&x,&y,&z);
change(x,y,1,1,n,z);
}
}
//system("pause");
return 0;
}