【例题1】求区间和
线段树单点修改,区间查询模板。
#include
#include
#include
#include
#include
#include
#define re register
#define int long long
#define drep(a,b,c) for(re int a(b) ; a>=(c) ; --a)
#define rep(a,b,c) for(re int a(b) ; a<=(c) ; ++a)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int M = 4e5+10;
int a[M];
int n,m;
struct tree{
int val,sum;
}t[M];
#define ls (k<<1)
#define rs (k<<1|1)
inline void pushup(int k) {
t[k].sum = t[ls].sum + t[rs].sum; }
inline void build(int k,int l,int r){
if(l == r){
t[k].sum = t[k].val = a[l];
return;
}
int mid = (l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(k);
}
inline void modify(int k,int l,int r,int x,int y){
if(l == x && r == x){
t[k].val = y;
t[k].sum += y;
return;
}
int mid = (l+r)>>1;
if(x <= mid) modify(ls,l,mid,x,y);
else modify(rs,mid+1,r,x,y);
pushup(k);
}
inline int query(int k,int l,int r,int x,int y){
if(x <= l && r <= y) return t[k].sum;
int mid = (l+r)>>1;
int res = 0;
if(x <= mid) res += query(ls,l,mid,x,y);
if(y > mid) res += query(rs,mid+1,r,x,y);
return res;
}
signed main(){
n = read(),m = read();
build(1,1,n);
while(m--){
int op = read(),x = read(),y = read();
if(op == 0) modify(1,1,n,x,y);
else printf("%lld\n",query(1,1,n,x,y));
}
return 0;
}
【例题2】区间修改
线段树区间修改,区间查询模板题,注意每次都要修改 p u s h d o w n pushdown pushdown。
#include
#include
#include
#include
#include
#include
#define re register
#define int long long
#define drep(a,b,c) for(re int a(b) ; a>=(c) ; --a)
#define rep(a,b,c) for(re int a(b) ; a<=(c) ; ++a)
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int M = 4e6+10;
int a[M];
int n,m;
struct tree{
int val,sum,lazy;
}t[M];
#define ls (k<<1)
#define rs (k<<1|1)
inline void pushup(int k) {
t[k].sum = t[ls].sum + t[rs].sum; }
inline void add(int k,int l,int r,int w){
t[k].sum += (r-l+1)*w;
t[k].lazy += w;
}
inline void pushdown(int k,int l,int r){
int mid = (l+r)>>1;
add(ls,l,mid,t[k].lazy);
add(rs,mid+1,r,t[k].lazy);
t[k].lazy = 0;
}
inline void build(int k,int l,int r){
if(l == r){
t[k].sum = t[k].val = a[l];
return;
}
int mid = (l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(k);
}
inline void modify(int k,int l,int r,int x,int y,int w){
if(x <=l && r <= y){
t[k].sum += (r-l+1)*w;
t[k].lazy += w;
return;
}
int mid = (l+r)>>1;
pushdown(k,l,r);
if(x <= mid) modify(ls,l,mid,x,y,w);
if(y > mid) modify(rs,mid+1,r,x,y,w);
pushup(k);
}
inline int query(int k,int l,int r,int x,int y){
if(x <= l && r <= y) return t[k].sum;
int mid = (l+r)>>1;
pushdown(k,l,r);
int res = 0;
if(x <= mid) res += query(ls,l,mid,x,y);
if(y > mid) res += query(rs,mid+1,r,x,y);
return res;
}
signed main(){
n = read(),m = read();
rep(i,1,n) a[i] = read();
build(1,1,n);
while(m--){
int op = read(),x = read(),y = read();
if(op == 1){
int w = read();
modify(1,1,n,x,y,w);
}
else printf("%lld\n",query(1,1,n,x,y));
}
return 0;
}
【例题3】公园遛狗
线段树求最大子段和模板。
考虑如何进行 p u s h u p pushup pushup 操作。我们在线段树里维护左端点开始的最大值 l m a x lmax lmax,右端点开始的最大值 r m a x rmax rmax,当前区间的最大值 m x mx mx,当前区间和 s u m sum sum。
注意在询问的时候,要返回一个结构体类型,便于将答案 p u s h u p pushup pushup。
#include
#include
#