线段树板子哪里出问题了???
查看原帖
线段树板子哪里出问题了???
546477
DESCENDANTSOFDRAGON楼主2023/1/10 20:58

可参考P3372

#include<bits/stdc++.h>
#define lid (id<<1)
#define rid (id<<1|1)
using namespace std;
const int maxn = 100000;
struct ser_tree{
    int l, r;
    int mx, sum;
    int lazy;
} tr[maxn * 4];
int n, m;
int a[maxn];
int t, x, y, k;
void build(int id, int l, int r) // 建树
{
    tr[id].l = l;
    tr[id].r = r;
    if(l==r)
    {
        tr[id].sum = a[l];
        tr[id].mx = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(lid, l, mid);
    build(rid, mid + 1, r);
    tr[id].sum = tr[lid].sum + tr[rid].sum;
    tr[id].mx = max(tr[lid].mx, tr[rid].mx);
}
// void modify(int id, int x, int val) // 单点修改原数组的某个值
// {
//     if(tr[id].l==tr[id].r)
//     {
//         tr[id].sum = tr[id].mx = val;
//         return;
//     }
//     int mid = (tr[id].l + tr[id].r) >> 1;
//     modify(x < mid ? lid : rid, x, val);
//     tr[id].sum = tr[lid].sum + tr[rid].sum;
//     tr[id].mx = max(tr[lid].mx, tr[rid].mx);    
// }
void pushdown(int id)//下放标记
{
    if(tr[id].lazy && tr[id].l != tr[id].r) //如果下放到lazy不为0,并且不是叶子节点
    {
        tr[lid].lazy += tr[id].lazy; //左儿子lazy+父亲节点lazy
        tr[rid].lazy += tr[id].lazy; //右儿子lazy+父亲节点lazy                                   
        tr[lid].sum += tr[id].lazy * (tr[lid].r - tr[lid].l + 1);//左儿子的sum+父亲节点lazy*(左儿子的右节点-左儿子的左节点+1)(个数)
        tr[rid].sum += tr[id].lazy * (tr[rid].r - tr[rid].l + 1);
        tr[id].lazy = 0;//父亲节点的lazy清空
    }
}

int query(int id, int l, int r) // 查询区间和
{
    
    if(tr[id].l==l && tr[id].r==r)
        return tr[id].sum;
    pushdown(id);    
    int mid = (tr[id].l + tr[id].r) >> 1;
    if(r<=mid)
        return query(lid, l, r);
    if(l>mid)
        return query(rid, l, r);
    return query(lid, l, mid) + query(rid, mid + 1, r);
}

void add(int id, int l, int r, int val) // 区间修改
{
    if(l<=tr[id].l && r>=tr[id].r) // 匹配到后
    {
        tr[id].lazy += val;//lazy累计
        tr[id].sum += val * (tr[id].r - tr[id].l + 1);//sum更新
        return;
    }
    pushdown(id);
    int mid = (l + r) >> 1;//中点
    if(r<=mid)
        add(lid, l, r, val);//左儿子
    else
        if(l>mid)
            add(rid, l, r, val);//右儿子
        else
            add(lid, l, mid, val), add(rid, mid + 1, r, val);
    tr[id].sum = tr[lid].sum + tr[rid].sum;//pushup  回溯之前更新每个点的信息
}
int main(){
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    build(1, 1, n);
    while(m--)
    {
        cin >> t >> x >> y;
        if(t==1)
        {
            cin >> k;
            add(1, x, y, k);
        }
        else
            cout << query(1, x, y) << endl;
    }
    system("pause"); 
    return 0;
}
2023/1/10 20:58
加载中...