线段树 add操作(惰性标记下推)

本文深入探讨了C++模板元编程的概念及其在标准模板库(STL)中的高级应用,包括如何利用模板元编程实现高效、灵活的数据结构和算法。详细介绍了模板参数、类型推导、模板函数和模板类的使用方法,以及如何结合STL容器和算法进行复杂操作。通过实际案例,展示了模板元编程在解决实际问题时的强大能力。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,(rt<<1|1)
#define INF  1000000100

const int maxn = 1000010;
int sum[maxn<<2],MIN[maxn<<2],MAX[maxn<<2],add[maxn<<2];
void pushUP(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]);
MIN[rt]=min(MIN[rt<<1],MIN[rt<<1|1]);
}
void maintain(int l,int r,int rt){
sum[rt]=MIN[rt]=MAX[rt]=0;
if(r>l) pushUP(rt);
sum[rt]+=add[rt]*(r-l+1); MAX[rt]+=add[rt]; MIN[rt]+=add[rt];
}
void pushDOWN(int l,int r,int rt){
if(l==r) return ;
if(add[rt]){
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
add[rt]=0;
}
}
void build(int l,int r,int rt){
add[rt]=0;
if(l==r){
    scanf("%d",&sum[rt]);
    add[rt]=MAX[rt]=MIN[rt]=sum[rt];
    return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushUP(rt);
}
int ql,qr,addv;
void update(int l,int r,int rt){
if(ql<=l&&r<=qr){
    add[rt]+=addv;
    sum[rt]+=addv*(r-l+1);
    MIN[rt]+=addv;
    MAX[rt]+=addv;
    return ;
}
pushDOWN(l,r,rt);
int m=(l+r)>>1;
if(ql<=m) update(lson);
if(qr >m) update(rson);
pushUP(rt);
}
int sum_,min_,max_;
void query(int l,int r,int rt,int ADD){
if(ql<=l&&r<=qr){
    sum_+=sum[rt]+ADD*(r-l+1);
    min_= min(min_,ADD+MIN[rt]);
    max_= max(max_,ADD+MAX[rt]);
}
else {
int m=(l+r)>>1;
if(ql<=m) query(lson,ADD+add[rt]);
if(qr >m) query(rson,ADD+add[rt]);
}
}
int main()
{
    void show(int l,int r,int rt);
    int n,Q;
    while(scanf("%d %d",&n,&Q)==2){
        build(1,n,1);
        while(Q--){
            int cmd;
            scanf("%d",&cmd);
            if(cmd==1){
                scanf("%d %d %d",&ql,&qr,&addv);
                update(1,n,1);
            }
            else {
                scanf("%d %d",&ql,&qr);
                sum_=0; min_=INF; max_=-INF;
                query(1,n,1,0);
                cout<<sum_<<" "<<min_<<" "<<max_<<endl;
            }
           // show(1,n,1);
        }
    }
    return 0;
}
void show(int l,int r,int rt){
if(l==r){
cout<<"L-->"<<" "<<l<<" "<<"R-->"<<" "<<r<<" "<<sum[rt]<<" "<<add[rt]<<endl;
   return ;
}
int m=(l+r)>>1;
show(lson);
show(rson);
cout<<"L-->"<<" "<<l<<" "<<"R-->"<<" "<<r<<" "<<sum[rt]<<" "<<add[rt]<<endl;
}

``` // 结构体版 #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define N 100005 #define LL long long #define lc u<<1 #define rc u<<1|1 LL w[N]; struct Tree{ //线段树 LL l,r,sum,add; }tr[N*4]; void pushup(LL u){ //上传 tr[u].sum=tr[lc].sum+tr[rc].sum; } void pushdown(LL u){ //下传 if(tr[u].add){ tr[lc].sum+=tr[u].add*(tr[lc].r-tr[lc].l+1), tr[rc].sum+=tr[u].add*(tr[rc].r-tr[rc].l+1), tr[lc].add+=tr[u].add, tr[rc].add+=tr[u].add, tr[u].add=0; } } void build(LL u,LL l,LL r){ //建树 tr[u]={l,r,w[l],0}; if(l==r) return; LL m=l+r>>1; build(lc,l,m); build(rc,m+1,r); pushup(u); } void change(LL u,LL l,LL r,LL k){ //区修 if(l<=tr[u].l&&tr[u].r<=r){ tr[u].sum+=(tr[u].r-tr[u].l+1)*k; tr[u].add+=k; return; } LL m=tr[u].l+tr[u].r>>1; pushdown(u); if(l<=m) change(lc,l,r,k); if(r>m) change(rc,l,r,k); pushup(u); } LL query(LL u,LL l,LL r){ //区查 if(l<=tr[u].l && tr[u].r<=r) return tr[u].sum; LL m=tr[u].l+tr[u].r>>1; pushdown(u); LL sum=0; if(l<=m) sum+=query(lc,l,r); if(r>m) sum+=query(rc,l,r); return sum; } int main(){ LL n,m,op,x,y,k; cin>>n>>m; for(int i=1; i<=n; i ++) cin>>w[i]; build(1,1,n); while(m--){ cin>>op>>x>>y; if(op==2)cout<<query(1,x,y)<<endl; else cin>>k,change(1,x,y,k); } return 0; }这是别人的 #include <bits/stdc++.h> using namespace std; #define lc p<<1 #define rc p<<1|1 const int N = 1e5+10; int n,m, a[N]; struct node {int l, r, sum, add; }; node tr[N*4]; void build(int p, int l, int r) { tr[p] = {l,r,a[l],0}; if(l == r) { tr[p].sum = a[l]; return; } int mid = (tr[p].l + tr[p].r) >> 1; build(lc, l, mid); build(rc, mid+1, r); tr[p].sum = tr[lc].sum + tr[rc].sum; } void updatedown(int p) { if(tr[p].add) { tr[lc].sum += (tr[lc].r - tr[lc].l + 1) * tr[p].add; tr[rc].sum += (tr[lc].r - tr[lc].l + 1) * tr[p].add; tr[lc].add += tr[p].add; tr[rc].add += tr[p].add; tr[p].add = 0; } } int query(int p, int l, int r) { // 当前区间被覆盖 if(tr[p].l >= l && tr[p].r <= r) return tr[p].sum; int mid = (tr[p].l + tr[p].r) >> 1; updatedown(p); // 先把帐算清 int sum = 0; if(mid >= l) sum += query(lc, l, mid); if(mid+1 <= r) sum += query(rc, mid+1, r); return sum; } void update(int p, int l, int r, int k) { if(tr[p].l >= l && tr[p].r <= r) { // 惰性标记 tr[p].sum += (k * (tr[p].r - tr[p].l + 1)); tr[p].add = k; return; } int mid = (tr[p].l + tr[p].r) >> 1; if(mid >= l) update(lc, l, mid,k); if(mid+1 <= r) update(rc, mid+1, r,k); tr[p].sum = tr[lc].sum + tr[rc].sum; } int main() { ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); cin >> n >> m; for(int i = 1; i <= n; i++) cin >> a[i]; build(1,1,n); while(m--) { int op,l,r,k; cin >> op; if(op == 1) { cin >> l >> r >> k; update(1,l,r,k); } else { cin >> l >> r; int s = query(1,l,r); cout << s << endl; } } return 0; }这是我的```为什么别人的能ac,我的是wa
03-17
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值