AC#1 10pts 求调

P3372 【模板】线段树 1

yi105011 @ 2024-11-21 20:26:20

#include<bits/stdc++.h>
using namespace std;
long long n , m , a[100010] , op , l , r , k;
struct node {
    long long l , r , num , sum;
} ans[1000010];
void build (long long l , long long r ,long long id) {
    ans[id].num = ans[id].sum = 0;
    ans[id].l = l; ans[id].r = r;
    if (l == r) {
        ans[id].num += a[l];
        return;
    }
    long long mid = (l + r) / 2;
    build (l , mid , id * 2);
    build (mid + 1 , r , id * 2 + 1);
    ans[id].num = ans[id * 2].num + ans[id * 2 + 1].num;
    return;
}
void f1 (long long id) {
    if (ans[id].r < l || r < ans[id].l) return;
    if (ans[id].l == ans[id].r) {
        ans[id].num += k;
        return;
    }
    if (l <= ans[id].l && ans[id].r <= r) {
        ans[id].sum = k;
        ans[id].num += (ans[id].r - ans[id].l + 1) * k;
        return;
    }
    f1 (id * 2); f1 (id * 2 + 1);
    ans[id].num = ans[id * 2].num + ans[id * 2 + 1].num;
    return;
}
void f2 (long long id , long long sum) {
    ans[id].sum += sum;
    ans[id].num += (ans[id].r - ans[id].l + 1) * sum;
    if (ans[id].r < l || r < ans[id].l) return;
    if (l <= ans[id].l && ans[id].r <= r) {
        k += ans[id].num;
        return;
    }
    f2 (id * 2 , ans[id].sum);
    f2 (id * 2 + 1, ans[id].sum);
    ans[id].sum = 0;
    return;
}
int main() {
    cin >> n >> m;
    for (int i = 1;i <= n;i ++) cin >> a[i];
    build (1 , n , 1);
    while (m --) {
        cin >> op >> l >> r;
        if (op == 1) {
            cin >> k;
            f1 ( 1 );
        }
        else {
            k = 0;
            f2 (1 , 0);
            /*for (int i = 1;i <= 9;i ++) {
                cout << ans[i].l << " ~ " << ans[i].r << " = " << ans[i].num << '\n';
            }*/
            cout << k << '\n';
        }
    }
    return 0;
};

提交记录


by chenxi2009 @ 2024-11-21 20:38:40

@yi105011 你的标记下传操作呢?


by chenxi2009 @ 2024-11-21 20:40:26

@yi105011 另:在非建树操作中,判断当前区间长度是否为 1 是没有意义的,这种情况被判断当前结点区间是询问区间的子区间这种情况覆盖。


by chenxi2009 @ 2024-11-21 20:41:24

my article with code


by yi105011 @ 2024-11-21 20:41:33

@chenxi2009 f2函数中的sum就是下传操作啊


by chenxi2009 @ 2024-11-21 20:43:09

@yi105011 f1 中缺失标记下传。每当你需要访问子结点的时候,都要确保它的值是正确的(获得了正确下传的标记)。


by chenxi2009 @ 2024-11-21 20:48:17

@yi105011 因为在任何修改和询问操作中,我们都需要用到标记下传,所以建议为它专门写一个函数 void pushdown(int id) 表示 id 结点把标记传给儿子。

可以参考我的专栏。


by yi105011 @ 2024-11-21 20:48:46

@chenxi2009 我f1函数中

f1 (id * 2);
f1 (id * 2 + 1);

就是下传标记啊


by chenxi2009 @ 2024-11-21 20:51:46

@yi105011 也许我们对下传的理解不同?下传是要你通过当前结点的 sum(标记),更新儿子结点的 sum num,并且清空当前已经下传的标记。


by chenxi2009 @ 2024-11-21 20:55:59

@yi105011 用你的代码修改了 f1f2,AC 了。

#include<bits/stdc++.h>
using namespace std;
long long n , m , a[100010] , op , l , r , k;
struct node {
    long long l , r , num , sum;
} ans[1000010];
void build (long long l , long long r ,long long id) {
    ans[id].num = ans[id].sum = 0;
    ans[id].l = l; ans[id].r = r;
    if (l == r) {
        ans[id].num += a[l];
        return;
    }
    long long mid = (l + r) / 2;
    build (l , mid , id * 2);
    build (mid + 1 , r , id * 2 + 1);
    ans[id].num = ans[id * 2].num + ans[id * 2 + 1].num;
    return;
}
void f1 (long long id) {
    if (ans[id].r < l || r < ans[id].l) return;
    if (l <= ans[id].l && ans[id].r <= r) {
        ans[id].sum += k;
        ans[id].num += (ans[id].r - ans[id].l + 1) * k;
        return;
    }
    if(ans[id].sum){
        ans[id << 1].num += ans[id].sum * (ans[id << 1].r - ans[id << 1].l + 1);
        ans[id << 1 | 1].num += ans[id].sum * (ans[id << 1 | 1].r - ans[id << 1 | 1].l + 1);
        ans[id << 1].sum += ans[id].sum;
        ans[id << 1 | 1].sum += ans[id].sum;
        ans[id].sum = 0;
    }
    f1 (id * 2); f1 (id * 2 + 1);
    ans[id].num = ans[id * 2].num + ans[id * 2 + 1].num;
    return;
}
void f2 (long long id) {
    if (ans[id].r < l || r < ans[id].l) return;
    if (l <= ans[id].l && ans[id].r <= r) {
        k += ans[id].num;
        return;
    }
    if(ans[id].sum){
        ans[id << 1].num += ans[id].sum * (ans[id << 1].r - ans[id << 1].l + 1);
        ans[id << 1 | 1].num += ans[id].sum * (ans[id << 1 | 1].r - ans[id << 1 | 1].l + 1);
        ans[id << 1].sum += ans[id].sum;
        ans[id << 1 | 1].sum += ans[id].sum;
        ans[id].sum = 0;
    }
    f2 (id * 2);
    f2 (id * 2 + 1);
    return;
}
int main() {
    cin >> n >> m;
    for (int i = 1;i <= n;i ++) cin >> a[i];
    build (1 , n , 1);
    while (m --) {
        cin >> op >> l >> r;
        if (op == 1) {
            cin >> k;
            f1 ( 1 );
        }
        else {
            k = 0;
            f2 (1);
            /*for (int i = 1;i <= 9;i ++) {
                cout << ans[i].l << " ~ " << ans[i].r << " = " << ans[i].num << '\n';
            }*/
            cout << k << '\n';
        }
    }
    return 0;
};

by chenxi2009 @ 2024-11-21 20:57:05

只是加了这个下传:

    if(ans[id].sum){
        ans[id << 1].num += ans[id].sum * (ans[id << 1].r - ans[id << 1].l + 1);
        ans[id << 1 | 1].num += ans[id].sum * (ans[id << 1 | 1].r - ans[id << 1 | 1].l + 1);
        ans[id << 1].sum += ans[id].sum;
        ans[id << 1 | 1].sum += ans[id].sum;
        ans[id].sum = 0;
    }

| 下一页