线段树模板
可能会有语法错误 供大家以后学习使用
自己
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e5+5;
int n,a[N];
struct Node{
int l,r;
int maxn,sum;
int lazy_tag=0;
}tre[N<<2];
void pushup(int pos){
tre[pos].maxn=max(tre[pos<<1].maxn,tre[pos<<1|1].maxn);
tre[pos].sum=tre[pos<<1].sum+tre[pos<<1|1].sum;
}
void pushdown(int pos){
if(tre[pos].lazy_tag==0) return ;
tre[pos<<1].lazy_tag+=tre[pos].lazy_tag;
tre[pos<<1|1].lazy_tag+=tre[pos].lazy_tag;
tre[pos<<1].sum+=tre[pos].lazy_tag*(tre[pos<<1].r-tre[pos<<1].l+1);
tre[pos<<1|1].sum+=tre[pos].lazy_tag*(tre[pos<<1|1].r-tre[pos<<1|1].l+1);
tre[pos<<1].maxn+=tre[pos].lazy_tag;
tre[pos<<1|1].maxn+=tre[pos].lazy_tag;
tre[pos].lazy_tag=0;
}
//建树
void build(int l,int r,int pos){
tre[pos].l=l;
tre[pos].r=r;
if(l==r){
tre[pos].maxn=a[l];
tre[pos].sum=a[l];
return ;
}
int mid=l+r>>1;
build(l,mid,pos<<1);
build(mid+1,r,pos<<1|1);
pushup(pos);
}
//查询
int queryMax(int pos,int l,int r){
if(tre[pos].r<l||tre[pos].l>r) return 0;
if(tre[pos].l>=l&&tre[pos].r<=r) return tre[pos].maxn;
pushdown(pos);
return max(queryMax(pos<<1,l,r),queryMax(pos<<1|1,l,r));
}
int querySum(int pos,int l,int r){
if(tre[pos].r<l||tre[pos].l>r) return 0;
if(tre[pos].l>=l&&tre[pos].r<=r) return tre[pos].sum;
pushdown(pos);
return querySum(pos<<1,l,r)+querySum(pos<<1|1,l,r);
}
//单点修改
void update(int pos,int x,int val){
if(tre[pos].r==tre[pos].l){
tre[pos].maxn=val;
tre[pos].sum=val;
return ;
}
int mid=tre[pos].l+tre[pos].r>>1;
if(x<=mid) update(pos<<1,x,val);
else update(pos<<1|1,x,val);
pushup(pos);
}
void modify(int pos,int l,int r,int val){
if(tre[pos].r<l||tre[pos].l>r) return ;
if(tre[pos].l>=l&&tre[pos].r<=r){
tre[pos].sum+=(tre[pos].r-tre[pos].l+1)*val;
tre[pos].maxn+=val;
tre[pos].lazy_tag+=val;
return ;
}
pushdown(pos);
modify(pos<<1,l,r,val);
modify(pos<<1|1,l,r,val);
pushup(pos);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,n,1);
int t;
cin>>t;
while(t--){
int op;
cin>>op;
if(op==1){
int l,r;
cin>>l>>r;
cout<<queryMax(1,l,r)<<endl;
}
else if(op==2){
int l,r;
cin>>l>>r;
cout<<querySum(1,l,r)<<endl;
}
else{
int pos,v;
cin>>pos>>v;
update(1,pos,v);
}
}
// update(1,pos,val);
// query(1,l,r);
}
标程
#include <iostream>
using namespace std;
const int N = 1e5 + 5;
int a[N];
//代表当前区间a
struct Node {
int l, r;
int max, min;
int sum;
int lazy_tag = 0;
} tre[N << 2];
//区间信息从下往上,如果下层信息被修改(如端点修改,建树等,需要更新同步上层,以维护区间信息)
void pushup(int pos) {
tre[pos].max = max(tre[pos << 1].max, tre[pos << 1 | 1].max);
tre[pos].min = max(tre[pos << 1].min, tre[pos << 1 | 1].min);
tre[pos].sum = tre[pos << 1].sum + tre[pos << 1 | 1].sum;
}
//建立线段树:
void build(int l, int r, int pos) {
tre[pos].l = l;
tre[pos].r = r;
if (l == r) {
tre[pos].max = a[l];
tre[pos].min = a[l];
tre[pos].sum = a[l];
return ;
}
int mid = l + r >> 1;
build(l, mid, pos << 1);
build(mid + 1, r, pos << 1 | 1);
pushup(pos);
}
//区间上对数据进行修改
//注意:修改操作是为了对查询服务的,因此,修改不必要马上更新所有包含该点信息的节点上,只需要做上标记
//当查询查到这里,再更新也不迟。
void pushdown(int pos) {
//把buff从上一层传递到下一层
if (tre[pos].lazy_tag == 0) return ;
//lazy-tag需要被传递到下一层,以保证传递信息的不丢失
tre[pos << 1].lazy_tag += tre[pos].lazy_tag;
tre[pos << 1 | 1].lazy_tag += tre[pos].lazy_tag;
//sum,max,min传递
tre[pos << 1].sum += tre[pos].lazy_tag * (tre[pos << 1].r - tre[pos << 1].l + 1);
tre[pos << 1 | 1].sum += tre[pos].lazy_tag * (tre[pos << 1 | 1].r - tre[pos << 1 | 1].l + 1);
//max,min
tre[pos << 1].max += tre[pos].lazy_tag;
tre[pos << 1 | 1].max += tre[pos].lazy_tag;
tre[pos << 1].min += tre[pos].lazy_tag;
tre[pos << 1 | 1].min += tre[pos].lazy_tag;
//当传递完之后,pos的tag应该清零,表示当前区间没有需要传递下去的东西
tre[pos].lazy_tag = 0;
}
void modify(int pos, int L, int R, int val) {
if (tre[pos].r < L || tre[pos].l > R) return;
if (tre[pos].l >= L && tre[pos].r <= R) {
tre[pos].sum += (tre[pos].r - tre[pos].l + 1) * val;
tre[pos].max += val;
tre[pos].min += val;
tre[pos].lazy_tag += val;
return ;
}
/*
当区间修改操作:需要递归到下一层时:也就是说半包含状态下
需要先去往下更新lazy-tag,因为为了保证数据的准确性,不能在递归的修改的时候,上层还有没传递下来的数值
所以这块需要从上往下进行tag的下放。
*/
pushdown(pos);
modify(pos << 1, L, R, val);
modify(pos << 1 | 1, L, R , val);
pushup(pos);
}
int queryMax(int pos, int L, int R) {
if (tre[pos].r < L || tre[pos].l > R) return 0;
if (tre[pos].l >= L && tre[pos].r <= R) return tre[pos].max;
pushdown(pos);
return max(queryMax(pos << 1, L, R), queryMax(pos << 1 | 1, L, R));
}
int querySum(int pos, int L, int R) {
if (tre[pos].r < L || tre[pos].l > R) return 0;
if (tre[pos].l >= L && tre[pos].r <= R) return tre[pos].sum;
pushdown(pos);
return querySum(pos << 1, L, R) + querySum(pos << 1 | 1, L, R);
}
//需要你修改的点
void update(int pos, int x, int val) {
if (tre[pos].l == tre[pos].r) {
tre[pos].max = val;
tre[pos].min = val;
tre[pos].sum = val;
return ;
}
int mid = tre[pos].l + tre[pos].r >> 1;
if (x <= mid) update(pos << 1, x, val);
else update(pos << 1 | 1, x, val);
pushup(pos);
}
int main(void)
{
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
build(1, n, 1);//l……n, 根节点从1开始
int T;
cin >> T;
while (T--) {
int op;
cin >> op;
if (op == 1) {
int l, r, val;
cin >> l >> r >> val;
modify(1, l, r, val);
} else if (op == 2) {
int l, r;
cin >> l >> r;
cout << queryMax(1, l, r) << '\n';
} else if (op == 3){
int l, r;
cin >> l >> r;
cout << querySum(1, l, r) << '\n';
} else if (op == -1) {
for (int i = 1; i <= n; i++) {
cout << querySum(1, i, i) << ' ';
}
cout << '\n';
}
}
return 0;
}