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

#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 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;
}
else {
int m=(l+r)>>1;
if(ql<=m) update(lson);
if(qr >m) update(rson);
}
maintain(l,r,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()
{
    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;
            }

        }
    }
    return 0;
}



``` // 结构体版 #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
#include<bits/stdc++.h> using namespace std; #define int long long const int N = 1e5 + 9; struct node { int laz; int num; //存储区间和 }tree[4 * N]; int a[N]; int n, m; void build(int id, int l, int r) { //对树的节点Id进行建树,节点id的管辖区域为l~r if (l == r) { tree[id].num = a[l]; return; } int mid = l + r >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); tree[id].num = tree[id << 1].num + tree[id << 1 | 1].num; } void pushdown(int id, int l, int r) { //对id节点的laz进行向下传递 if (tree[id].laz) { //laz节点是当前节点已经处理过,需要传递给下一个节点 int mid = l + r >> 1; tree[id << 1].laz += tree[id].laz; tree[id << 1].num += tree[id].laz * (mid - l + 1); //传递给左子树 tree[id << 1 | 1].laz += tree[id].laz; tree[id << 1 | 1].num += tree[id].laz * (r - mid); //传递给右子树 tree[id].laz = 0; //传递完成后变为0 } return; } void add(int id,int l,int r,int x,int y,int v) { if (l >= x && r <= y) { tree[id].num += v * (r - l + 1); tree[id].laz += v; //到达一个完全区间,更新它的值,然后不再向下更新 return; } int mid = l + r >> 1; pushdown(id, l, r); if (mid >= x)add(id << 1, l, mid, x, y, v); if (mid < y)add(id << 1 | 1, mid + 1, r, x, y, v); tree[id].num = tree[id << 1].num + tree[id << 1 | 1].num; return; } int query(int id, int l, int r, int x, int y) { if (l >= x && r <= y) return tree[id].num; pushdown(id, l, r); //在需要查询这个节点的子节点时需要下放该节点的laz int mid = l + r >> 1; int ans = 0; if (mid >= x)ans += query(id << 1, l, mid, x, y); if (mid < y)ans += query(id << 1 | 1, mid + 1, r, x, y); return ans; } signed main() { cin >> n >> m; for (int i = 1; i <= n; i++)cin >> a[i]; while (m--) { int p, x, y, k; cin >> p; if (p == 1) { cin >> x >> y >> k; add(1, 1, n, x, y, k); } else { cin >> x >> y; cout << query(1, 1, n, x, y) << endl; } } return 0; } 我的代码可以实时查询区间和吗
03-09
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值