题目大意:维护一个长度为 N 的序列,支持区间修改、区间查询两种操作。
update on 2019.4.3
线段树分为指针式线段树和堆式线段树。指针式线段树的优点是空间较小,可以进行可持久化操作。堆式线段树的优点是可以不必记录左右儿子,缺点是区间要开到四倍,且不能可持久化,不过对于树套树的外层线段树来说,采用堆式线段树看起来更加直观。
代码如下
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n,m;
long long a[maxn];
struct node{
#define ls(x) t[x].lc
#define rs(x) t[x].rc
int lc,rc;
long long sum,tag;
}t[maxn<<1];
int tot,root;
inline void pushup(int x){
t[x].sum=t[ls(x)].sum+t[rs(x)].sum;
}
inline void pushdown(int x,int l,int r){
int mid=l+r>>1;
t[ls(x)].sum+=(mid-l+1)*t[x].tag,t[ls(x)].tag+=t[x].tag;
t[rs(x)].sum+=(r-mid)*t[x].tag,t[rs(x)].tag+=t[x].tag;
t[x].tag=0;
}
int build(int l,int r){
int x=++tot;
if(l==r){t[x].sum=a[l];return x;}
int mid=l+r>>1;
ls(x)=build(l,mid),rs(x)=build(mid+1,r);
pushup(x);
return x;
}
void modify(int o,int l,int r,int x,int y,long long val){
if(l==x&&r==y){t[o].sum+=(r-l+1)*val,t[o].tag+=val;return;}
int mid=l+r>>1;
pushdown(o,l,r);
if(y<=mid)modify(ls(o),l,mid,x,y,val);
else if(x>mid)modify(rs(o),mid+1,r,x,y,val);
else modify(ls(o),l,mid,x,mid,val),modify(rs(o),mid+1,r,mid+1,y,val);
pushup(o);
}
long long query(int o,int l,int r,int x,int y){
if(l==x&&r==y)return t[o].sum;
int mid=l+r>>1;
pushdown(o,l,r);
if(y<=mid)return query(ls(o),l,mid,x,y);
else if(x>mid)return query(rs(o),mid+1,r,x,y);
else return query(ls(o),l,mid,x,mid)+query(rs(o),mid+1,r,mid+1,y);
}
void read_and_parse(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
root=build(1,n);
}
void solve(){
while(m--){
int opt,val,l,r;
scanf("%d",&opt);
if(opt==1){
scanf("%d%d%d",&l,&r,&val);
modify(root,1,n,l,r,val);
}else{
scanf("%d%d",&l,&r);
printf("%lld
",query(root,1,n,l,r));
}
}
}
int main(){
read_and_parse();
solve();
return 0;
}
#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=1e6+10;
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll read(){
ll x=0,f=1;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
return f*x;
}
/*--------------------------------------------------------*/
int n,m,a[maxn];
#define ls(o) o<<1
#define rs(o) o<<1|1
struct node{ll sum,tag;}t[maxn<<2];
inline void pushup(int o){t[o].sum=t[ls(o)].sum+t[rs(o)].sum;}
inline void pushdown(int o,int l,int r){
int mid=l+r>>1;
t[ls(o)].sum+=t[o].tag*(mid-l+1),t[ls(o)].tag+=t[o].tag;
t[rs(o)].sum+=t[o].tag*(r-mid),t[rs(o)].tag+=t[o].tag;
t[o].tag=0;
}
void build(int o,int l,int r){
if(l==r){t[o].sum=a[l];return;}
int mid=l+r>>1;
build(ls(o),l,mid),build(rs(o),mid+1,r);
pushup(o);
}
void modify(int o,int l,int r,int x,int y,ll val){
if(l==x&&r==y){t[o].sum+=val*(r-l+1),t[o].tag+=val;return;}
int mid=l+r>>1;
pushdown(o,l,r);
if(y<=mid)modify(ls(o),l,mid,x,y,val);
else if(x>mid)modify(rs(o),mid+1,r,x,y,val);
else modify(ls(o),l,mid,x,mid,val),modify(rs(o),mid+1,r,mid+1,y,val);
pushup(o);
}
ll query(int o,int l,int r,int x,int y){
if(l==x&&r==y)return t[o].sum;
int mid=l+r>>1;
pushdown(o,l,r);
if(y<=mid)return query(ls(o),l,mid,x,y);
else if(x>mid)return query(rs(o),mid+1,r,x,y);
else return query(ls(o),l,mid,x,mid)+query(rs(o),mid+1,r,mid+1,y);
}
void read_and_parse(){
n=read(),m=read();
for(int i=1;i<=n;i++)a[i]=read();
build(1,1,n);
}
void solve(){
while(m--){
int opt=read();
if(opt==1){
int l=read(),r=read(),x=read();
modify(1,1,n,l,r,x);
}else{
int l=read(),r=read();
printf("%lld
",query(1,1,n,l,r));
}
}
}
int main(){
//freopen("D:\学习\Code\对拍\data.in");
//freopen("D:\学习\Code\对拍\test.out");
read_and_parse();
solve();
return 0;
}