给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。
2、“Q l r”,表示询问 数列中第 l~r 个数的和。
对于每个询问,输出一个整数表示答案。
输入格式
第一行两个整数N,M。
第二行N个整数A[i]。
接下来M行表示M条指令,每条指令的格式如题目描述所示。
输出格式
对于每个询问,输出一个整数表示答案。
每个答案占一行。
数据范围
1≤N,M≤105,
|d|≤10000,
|A[i]|≤1000000000
输入样例:
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
输出样例:
4
55
9
15
今天上高数发现以前学的都忘的有一点多,拿出一个半小时,今天复习了以前的高数。
今天刚好要学线段树,于是我去做了一下线段树的第一讲,一个简单的整数问题,我想刚好可以入门学一下线段树,然后我就去试着做了一下,不做不知道一做吓一跳,简单个毛线,给大家看个难度图压压惊。
然后我就开始仔细的去看y总的视频去学一下线段树,y总没有留下代码,只有树状数组的代码,所以我刚开始学线段树的很尴尬,于是我就把y总写的代码来回翻视频给大家把所有的树的操作过程代码截屏下来了。减少来回翻的繁琐。
y总的视频
下面是各个操作的图
更新目前的值(左右两个子树的的值)
向下更新左右子节点的值。
修改 l - r 区间的值(增加k)
查询操作(从l到r)的和。
最后说一下代码吧
代码如下
#include<iostream>
using namespace std;
const int N=1e5+10;
typedef long long LL;
int a[N];
struct Node
{
int l,r;
LL w,add;//add叫懒人节点,因为这样可以减少操作步数
} trie[N*4];//用结构体保存线段树
void pushup(int u)//更新该点的操作
{
trie[u].w=trie[u<<1].w+trie[u<<1|1].w;//左右子节点的和
}
void build(int u,int l,int r)//建立线段树
{
if(l==r)
{
trie[u]={l,r,a[l],0};
}
else
{
trie[u]={l,r};
int mid=l+r>>1;//这个是我一致bug的操作,应该是l+r
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
trie[u].add=0;
}
}
void pushdown(int u)//更新左右子树
{
auto &root=trie[u],&lef=trie[u<<1],&rig=trie[u<<1|1];
if(root.add)
{
lef.add+=root.add;lef.w+=(LL)(lef.r-lef.l+1)*(root.add);
rig.add+=root.add;rig.w+=(LL)(rig.r-rig.l+1)*(root.add);
root.add=0;
}
}
void modify(int u,int l,int r,int k)
{
if(trie[u].l>=l&&trie[u].r<=r)
{
trie[u].add+=k;
trie[u].w+=(LL)(trie[u].r-trie[u].l+1)*k;//不用懒人节点了
}
else
{
pushdown(u);//要用到懒人节点先更新
int mid=trie[u].l+trie[u].r>>1;
if(l<=mid) modify(u<<1,l,r,k);
if(mid<r) modify(u<<1|1,l,r,k);
pushup(u);//最后更新目前的子节点
}
}
LL query(int u,int l,int r)
{
if(trie[u].l>=l&&trie[u].r<=r)
{
return trie[u].w;
}
else
{
pushdown(u);//用到懒人节点
LL res=0;
int mid=trie[u].l+trie[u].r>>1;
if(l<=mid) res+=query(u<<1,l,r);
if(r>mid) res+=query(u<<1|1,l,r);
return res;
}
}
int main(void)
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
// cout<<query(1,1,2)<<endl;
while(m--)
{
char op[2];
cin>>op;
if(*op=='Q')
{
int a,b;
cin>>a>>b;
cout<<query(1,a,b)<<endl;
}
else
{
int a,b,d;
cin>>a>>b>>d;
modify(1,a,b,d);
}
}
}