线段树全WA求调(样例已过)

P3372 【模板】线段树 1

rainygame @ 2023-03-23 15:00:47

RT。没有一个对的:

#include <bits/stdc++.h>
using namespace std;
#define MAXN 500001

int n, m, x, y, opt;
long long k;
long long a[MAXN];

struct Tree{  // 线段树结点 
    int l, r, lzt;  // lzt表示lazytag,懒标记 
    long long sum;
}tree[MAXN<<2];  // 注意要开到4倍空间 

void build(int l, int r, int p){  // 建线段树
    tree[p].l = l;  // 定义左边界 
    tree[p].r = r;  // 定义右边界
    if (l == r){  // 如果[l,r]为一个单点
        tree[p].sum = a[l];  // 则它的权值为那个单点的数 
        return;
    }

    int mid = (l+r)>>1;
    build(l, mid, p<<1);  // 递归查找左儿子 
    build(mid+1, r, (p<<1)+1);  // 递归查找右儿子
    tree[p].sum = tree[p<<1].sum + tree[(p<<1)+1].sum;  // 即为两儿子之和 
}

void push_down(int p){
    if (tree[p].lzt){
        tree[p<<1].lzt += tree[p].lzt;  //左右儿子分别加上父亲的lz
        tree[(p<<1)+1].lzt += tree[p].lzt;
        int mid = (tree[p].l + tree[p].r) >> 1;
        tree[p<<1].sum += tree[p].lzt * (mid-tree[p<<1].l+1);  //左右分别求和加起来
        tree[(p<<1)+1].sum += tree[p].lzt * (tree[(p<<1)+1].r-mid);
        tree[p].lzt = 0; //父亲lazytag归零
    }
}

void add(int l, int r, long long k, int p){  // [l,r]加上k,现在搜到了p 
    if (tree[p].l >= l && tree[p].r <= r){  // 完全在区间内 
        tree[p].sum += k;
        tree[p].lzt += k;  // 记录lazytag 
        return;
    }
    push_down(p);
    if (tree[p<<1].r >= l) add(l, r, k, p<<1);  // 递归左儿子 
    if (tree[(p<<1)+1].l <= r) add(l, r, k, (p<<1)+1);  // 递归右儿子
    tree[p].sum = tree[p<<1].sum + tree[(p<<1)+1].sum;  // 加和  
}

long long query(int l, int r, int p){  // 查询区间[l,r]的和
    if (tree[p].l >= l && tree[p].r <= r) return tree[p].sum;
    push_down(p);
    long long ans = 0;
    if (tree[p].l == tree[p].r) return ans;  // 单点 
    if (tree[p<<1].r >= l) ans += query(l, r, p<<1);  // 递归左儿子 
    if (tree[(p<<1)+1].l <= r) ans += query(l, r, (p<<1)+1);  // 递归右儿子 
    return ans;  // 返回 
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> m;
    for (int i=1; i<=n; i++) cin >> a[i];
    build(1, n, 1);

    while (m--){
        cin >> opt;
        if (opt == 1){  // 区间修改
            cin >> x >> y >> k;
            add(x, y, k, 1);
        }else{  // 区间查询 
            cin >> x >> y;
            cout << query(x, y, 1) << '\n';
        }
    }

    return 0;
}

是学着 这个 来写的。


by yllcm @ 2023-03-23 15:24:42

@rainygame add 没乘区间长度


by rainygame @ 2023-03-23 15:28:17

@yllcm 已A,谢谢


|