线段树超时?打了标记!

P3372 【模板】线段树 1

Kaedehara_zgb @ 2023-10-20 09:48:32

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100100;
int n, m, i, a[N], ans;
struct no {
    int sum;
};
struct lazy {
    int add;
};
struct node {
    lazy t;
    no val;
    int len;
}seg[N * 4];
no operator + (const no &l, const no &r) {
    return {l.sum + r.sum};
}
lazy operator + (const lazy &v, const lazy &t) {
    return {v.add+ t.add};
}
void update(int id) {
    seg[id].val.sum = seg[id * 2].val.sum + seg[id * 2 + 1].val.sum;
    seg[id].len = seg[id * 2].len * 2;
}
void build(int id, int l, int r) {
    if(l == r) {
        seg[id].val.sum = a[l];
        seg[id].len = 1;
        return;
    }
    int mid = (l + r) / 2;
    build(id * 2, l, mid);
    build(id * 2 + 1, mid + 1, r);
    update(id);
}
void setlazy(int id, lazy t) {
    seg[id].val.sum = seg[id].val.sum + t.add * seg[id].len;
    seg[id].t = seg[id].t + t;
}
void pushdown(int id) {
    if(seg[id].t.add != 0) {
        setlazy(id * 2, seg[id].t);
        setlazy(id * 2 + 1, seg[id].t);
        seg[id].t.add = 0;
    }
}
int query(int id, int l, int r, int ql, int qr) {
    if(l == qr && r == qr) return seg[id].val.sum;
    int mid = (l + r) / 2;
    pushdown(id);
    if(qr <= mid) return query(id * 2, l, mid, ql, qr);
    else if(ql > mid) return query(id * 2 + 1, mid + 1, r, ql, qr);
    else return query(id * 2, l, mid, ql, mid) + query(id * 2 + 1, mid + 1, r, mid + 1, qr);    
}
void modify(int id, int l, int r, int ql, int qr, lazy t) {
    if(l == qr && r == qr) {setlazy(id, t); return;}
    int mid = (l + r) / 2;
    pushdown(id);
    if(qr <= mid) return modify(id * 2, l, mid, ql, qr, t);
    else if(ql > mid) return modify(id * 2 + 1, mid + 1, r, ql, qr, t);
    else {
        modify(id * 2, l, mid, ql, mid, t);
        modify(id * 2 + 1, mid + 1, r, mid + 1, qr, t);
    }
    update(id);
}
signed main () {
    scanf("%lld %lld", &n, &m);
    for (i = 1; i <= n; ++i) scanf("%lld", &a[i]);
    build(1, 1, n);
    while(m--) {
        int ty;
        scanf("%lld", &ty);
        if(ty == 1) {
            int l, r, d;
            scanf("%lld %lld %lld", &l, &r, &d);
            modify(1, 1, n, l, r, (lazy){d});
        } else {
            int l, r;
            scanf("%lld %lld",&l, &r);
            ans = query(1, 1, n, l, r);
            printf("%lld\n", ans);
        }
    }
}

我很难理解,题解没加标记没有超,我加了反而还超了,大佬帮忙看看问题在哪里。谢谢!


by gghack_Nythix @ 2023-10-20 10:08:22

查询区间不需要查到叶子节点上吧


by Buried_Dream @ 2023-10-20 10:09:36

if(l == qr && r == qr) return seg[id].val.sum;

这都查到叶子节点了吧


by kyEEcccccc @ 2023-10-20 10:25:52

@Buried_Dream 仔细看他的写法,不会查到叶子上。

TLE 的问题我不清楚,但是

if(qr <= mid) return modify(id * 2, l, mid, ql, qr, t);
else if(ql > mid) return modify(id * 2 + 1, mid + 1, r, ql, qr, t);
else {
    modify(id * 2, l, mid, ql, mid, t);
    modify(id * 2 + 1, mid + 1, r, mid + 1, qr, t);
}
update(id);

会导致你有时候不 update,答案错误。


by kyEEcccccc @ 2023-10-20 10:26:20

@Kaedehara_zgb


by Buried_Dream @ 2023-10-20 10:35:52

@Retired_kyEEcccccc 为什么他这个会有的时候不 update,退役人看不出来了/kk


by Kaedehara_zgb @ 2023-10-20 10:36:24

@Retired_kyEEcccccc 就只有超时没有答案错误


by kyEEcccccc @ 2023-10-20 10:42:36

@Buried_Dream 上两行 return


by Buried_Dream @ 2023-10-20 10:42:55

@Retired_kyEEcccccc

l == qr && r == qr

那 l应该等于r吧,我感觉查到叶子节点了


by Kaedehara_zgb @ 2023-10-20 10:44:27

@Retired_kyEEcccccc 了解,改好了,因为modify是复制query的忘记删return了。但还是超的![结果] O2开了也是这样


by Buried_Dream @ 2023-10-20 10:45:12

@Retired_kyEEcccccc

我大概明白了,他TLE的原因就是因为都查到叶子节点了,然后没update所以答案错了


| 下一页