线段树(区间树)
题:洛谷P3372 (区间加,查询)
题:洛谷P3373 (区间加,乘,查询)
1.数组输入
2.建树(没啥特别注意的)
3.添加懒惰标记(如果没有全包含在修改区间内,则继续将懒惰标记下发给子结点)
4.查询(如果没有全包含在查询区间内,则继续将懒惰标记下发给子结点,并修改结点值)
自己写的基操代码,还不怎么熟练,应该还有些漏洞还没看出来(lazy长度为4n,n为数组长度)
#include <bits/stdc++.h>
#define int long long
using namespace std;
int arr[100005];
int lazy[400005];
int node[400005];
int n,m;
void build(int a,int b,int step)
{
if(a==b){
node[step]=arr[a];
return ;
}
int m=(a+b)>>1;
build(a,m,step*2);
build(m+1,b,step*2+1);
node[step]=node[step*2]+node[step*2+1];
}
void update(int a,int b,int l,int r,int step,int p)
{
if( a<=l&&r<=b){
lazy[step]+=p;
node[step] += (r - l + 1) * p;
return ;
}
int m=(l+r)>>1;
if(lazy[step]&&l!=r){
node[step*2]+=(m-l+1)*lazy[step];
node[step*2+1]+=(r-m)*lazy[step];
lazy[step*2]+=lazy[step];
lazy[step*2+1]+=lazy[step];
lazy[step]=0;
}
if(a<=m) update(a,b,l,m,step*2,p);
if(b>m) update(a,b,m+1,r,step*2+1,p);
node[step]=node[step*2]+node[step*2+1];
}
int query(int a,int b,int l,int r,int step)
{
if(a<=l&&r<=b) return node[step];
int m=(l+r)>>1;
if(lazy[step]&&l!=r){
node[step*2]+=(m-l+1)*lazy[step];
node[step*2+1]+=(r-m)*lazy[step];
lazy[step*2]+=lazy[step];
lazy[step*2+1]+=lazy[step];
lazy[step]=0;
}
int ans=0;
if(a<=m) ans+=query(a,b,l,m,step*2);
if(b>m) ans+=query(a,b,m+1,r,step*2+1);
node[step]=node[step*2]+node[step*2+1];
return ans;
}
signed main()
{
cin >> n >> m;
for(int i=1;i<=n;i++)
cin >> arr[i] ;
build(1,n,1);
while(m--){
int x;cin >> x;
switch(x){
case 1 :{
int a,b,c;
cin >> a >>b >>c;
update(a,b,1,n,1,c);
break;
}
case 2 :{
int a,b;
cin >> a >>b ;
cout<<query(a,b,1,n,1)<<endl;
}
}
}
}