动态开点线段树(指针) WA 0 求助

P3372 【模板】线段树 1

ISTP @ 2024-03-12 19:19:35

在学动态开点,题面样例和手搓的小样例都过了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
struct stn{
    long long sum, lz_add;
    stn* lp;
    stn* rp;
};
long long a[maxn];
int n, m;
int cnt;
void build(int, int, stn*);
void update(int, int, int, int, long long, stn*);
long long query(int, int, int, int, stn*);
void push_down(int, int, stn*);
void push_up(stn*);
void check(stn*&);
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];
    stn root;
    stn* rootp = &root;
    build(1, n, rootp);
    while(m --){
        int opr, x, y;
        long long k;
        cin >> opr;
        if(opr == 1){
            cin >> x >> y >> k;
            update(1, n, x, y, k, rootp);
        }
        else{
            cin >> x >> y;
            cout << query(1, n, x, y, rootp) << '\n';
        }
    }
    return 0;
}
void check(stn* &p){
    if(p == nullptr){
        stn* childp = new stn;
        p = childp;
    }
    return ;
}
void build(int lf, int rt, stn* p){
    p->sum = p->lz_add = 0;
    p->lp = p->rp = nullptr;
    if(lf == rt){
        p->sum = a[lf];
        return ;
    }
    check(p->lp), check(p->rp);
    int mid = lf + rt >> 1;
    build(lf, mid, p->lp), build(mid + 1, rt, p->rp);
    push_up(p);
    return ;
}
void push_down(int lf, int rt, stn* p){
    int mid = lf + rt >> 1;
    p->lp->sum += p->lz_add * (mid - lf + 1);
    p->lp->lz_add += p->lz_add;
    p->rp->sum += p->lz_add * (rt - mid);
    p->rp->lz_add += p->lz_add;
    p->lz_add = 0;
    return ;
}
void push_up(stn* p){
    p->sum = p->lp->sum + p->rp->sum;
    return;
}
void update(int lf, int rt, int s, int t, long long val, stn* p){
    if(lf == s && rt == t){
        p->sum += val, p->lz_add += val;
        return ;
    }
    check(p->lp), check(p->rp);
    push_down(lf, rt, p);
    int mid = lf + rt >> 1;
    if(t <= mid) update(lf, mid, s, t, val, p->lp);
    else if(mid < s) update(mid + 1, rt, s, t, val, p->rp);
    else update(lf, mid, s, mid, val, p->lp), update(mid + 1, rt, mid + 1, t, val, p->rp);
    push_up(p);
    return ;
}
long long query(int lf, int rt, int s, int t, stn* p){
    if(lf == s && rt == t) return p->sum;
    check(p->lp), check(p->rp);
    push_down(lf, rt, p);
    int mid = lf + rt >> 1;
    if(t <= mid) return query(lf, mid, s, t, p->lp);
    else if(mid < s) return query(mid + 1, rt, s, t, p->rp);
    else return query(lf, mid, s, mid, p->lp) + query(mid + 1, rt, mid + 1, t, p->rp);
}

by ISTP @ 2024-03-12 19:48:19

自查出来了,update函数里更新写忘乘区间长度了。

if(lf == s && rt == t){
        p->sum += val, p->lz_add += val;
        return ;
    }

应该是

if(lf == s && rt == t){
        p->sum += val * (rt - lf + 1), p->lz_add += val;
        return ;
    }

此帖结。


|