[模板]线段树

codevs4927

1、注意代码是左闭右闭的线段树,mid在左区间内
2、打权值线段树时注意线段树右端点大于最大值

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define L(w) w << 1
#define R(w) w << 1|1
#define INF 1061109567
typedef long long LL;
using namespace std;
const int MAXN = 200000 + 50;
int L[MAXN << 2],R[MAXN << 2],maxn[MAXN << 2],minx[MAXN << 2],M1[MAXN << 2],M2[MAXN << 2];
LL sum[MAXN << 2];
int A[MAXN];
void update(int w){
    sum[w] = sum[L(w)] + sum[R(w)];
    minx[w] = min(minx[L(w)],minx[R(w)]);
    maxn[w] = max(maxn[L(w)],maxn[R(w)]);
}
void spread1(int w){
    if(M1[w] == -1)return;
    int m = M1[w];
    M1[w] = -1;
    minx[L(w)] = maxn[L(w)] = m;
    minx[R(w)] = maxn[R(w)] = m;
    sum[L(w)] = m*(R[L(w)] - L[L(w)] + 1);
    sum[R(w)] = m*(R[R(w)] - L[R(w)] + 1);
    M2[L(w)] = M2[R(w)] = 0;
    M1[L(w)] = M1[R(w)] = m;
}
void spread(int w){
    if(M1[w] != -1){
        spread1(w);
    }
    int m = M2[w];
    if(!m)return;
    M2[w] = 0;
    spread1(L(w));
    spread1(R(w));
    maxn[L(w)] += m;
    maxn[R(w)] += m;
    minx[L(w)] += m;
    minx[R(w)] += m;
    sum[L(w)] += m*(R[L(w)] - L[L(w)] + 1);
    sum[R(w)] += m*(R[R(w)] - L[R(w)] + 1);
    M2[L(w)] += m;
    M2[R(w)] += m;
}
void build(int w,int l,int r){
    L[w] = l;R[w] = r;
    if(l == r){
        sum[w] = minx[w] = maxn[w] = A[l];
        return;
    }
    int mid = l + r >> 1;
    build(L(w),l,mid);
    build(R(w),mid + 1,r);
    update(w);
}
void cover(int w,int l,int r,int v){
    if(L[w] == l && R[w] == r){
        M2[w] = 0;
        M1[w] = v;
        minx[w] = maxn[w] = v;
        sum[w] = v*(R[w] - L[w] + 1);
        return;
    }
    spread(w);//重置前,先下放标记 
    int mid = L[w] + R[w] >> 1;
    if(r <= mid)cover(L(w),l,r,v);
    else if(l > mid)cover(R(w),l,r,v);
    else cover(L(w),l,mid,v),cover(R(w),mid + 1,r,v);
    update(w);
}
void add(int w,int l,int r,int v){
    if(L[w] == l && R[w] == r){
        spread1(w);
        M2[w] += v;
        minx[w] += v;
        maxn[w] += v;
        sum[w] += v*(R[w] - L[w] + 1);
        return;
    }
    spread(w);
    int mid = L[w] + R[w] >> 1;
    if(r <= mid)add(L(w),l,r,v);
    else if(l > mid)add(R(w),l,r,v);
    else add(L(w),l,mid,v),add(R(w),mid + 1,r,v);
    update(w);
}
LL ask_sum(int w,int l,int r){
    if(L[w] == l && R[w] == r){
        return sum[w];
    }
    spread(w);
    LL ans = 0;
    int mid = L[w] + R[w] >> 1;
    if(r <= mid)ans = ask_sum(L(w),l,r);
    else if(l > mid)ans = ask_sum(R(w),l,r);
    else ans = ask_sum(L(w),l,mid) + ask_sum(R(w),mid + 1,r);
    return ans;
}
int ask_max(int w,int l,int r){
    if(L[w] == l && R[w] == r){
        return maxn[w];
    }
    spread(w);
    int mid = L[w] + R[w] >> 1;
    int ans = -INF;
    if(r <= mid)ans = ask_max(L(w),l,r);
    else if(l > mid)ans = ask_max(R(w),l,r);
    else ans = max(ask_max(L(w),l,mid),ask_max(R(w),mid + 1,r));
    return ans;
}
int ask_min(int w,int l,int r){
    if(L[w] == l && R[w] == r){
        return minx[w];
    }
    spread(w);
    int mid = L[w] + R[w] >> 1;
    int ans = INF;
    if(r <= mid)ans = ask_min(L(w),l,r);
    else if(l > mid)ans = ask_min(R(w),l,r);
    else ans = min(ask_min(L(w),l,mid),ask_min(R(w),mid + 1,r));
    return ans;
}
int n,m,a,b,c;
string s;
int main(){
    memset(M1,-1,sizeof(M1));
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i ++){
        scanf("%d",&A[i]);
    }
    build(1,1,n);
    for(int i = 1;i <= m;i ++){
        cin >> s;
        if(s == "add"){
            scanf("%d%d%d",&a,&b,&c);
            add(1,a,b,c);
        }
        else if(s == "set"){
            scanf("%d%d%d",&a,&b,&c);
            cover(1,a,b,c);
        }
        else if(s == "sum"){
            scanf("%d%d",&a,&b);
            if(a > b)swap(a,b);
            printf("%lld\n",ask_sum(1,a,b));
        }
        else if(s == "max"){
            scanf("%d%d",&a,&b);
            printf("%d\n",ask_max(1,a,b));
        }
        else if(s == "min"){
            scanf("%d%d",&a,&b);
            printf("%d\n",ask_min(1,a,b));
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是acwing模板线段的示例代码: ```cpp const int N = 100010; int n, m; int a[N]; struct Node { int l, r; int v, lazy; } tree[N * 4]; void pushup(int x) { tree[x].v = tree[x * 2].v + tree[x * 2 + 1].v; } void pushdown(int x) { if (tree[x].lazy) { int l = tree[x].l, r = tree[x].r; int mid = (l + r) >> 1; tree[x * 2].v += tree[x].lazy * (mid - l + 1); tree[x * 2 + 1].v += tree[x].lazy * (r - mid); tree[x * 2].lazy += tree[x].lazy; tree[x * 2 + 1].lazy += tree[x].lazy; tree[x].lazy = 0; } } void build(int x, int l, int r) { tree[x].l = l, tree[x].r = r; if (l == r) { tree[x].v = a[l]; return; } int mid = (l + r) >> 1; build(x * 2 l, mid); build(x * 2 + 1, mid +1, r); pushup(x); } void modify(int x, int l, int r, int val) { if (tree[x].l >= l && tree[x].r <= r) { tree[x].v += val * (tree[x].r - tree[x].l + 1); tree[x].lazy += val; return; } pushdown(x); int mid = (tree[x].l + tree[x].r) >> 1; if (l <= mid) modify(x * 2, l, r, val); if (r > mid) modify(x * 2 + 1, l, r, val); pushup(x); } int query(int x, int l, int r) { if (tree[x].l >= l && tree[x].r <= r) { return tree[x].v; } pushdown(x); int mid = (tree[x].l + tree[x].r) >> 1; int sum = 0; if (l <= mid) sum += query(x * 2, l, r); if (r > mid) sum += query(x * 2 + 1, l, r); return sum; } int main() { cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> a[i]; } build(1, 1, n); while (m--) { int op, l, r, val; cin >> op; if (op == 1) { cin >> l >> r >> val; modify(1, l, r, val); } else if (op == 2) { cin >> l >> r; cout << query(1, l, r) << endl; } } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值