线段树板子求调
查看原帖
线段树板子求调
84132
昒昕楼主2022/8/10 20:46

样例没过,基本跟题解一模一样了,就是找不出。

(一个暑假过了连线段树板子都敲不来了

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

const int maxn=1e5+10;
typedef long long ll;
ll a[maxn],w[maxn*4],lazy[maxn*4];
void pushup(int u) { // 更新根节点
    w[u]=w[u*2]+w[u*2+1];
}
void build(int u,int l,int r) {
    lazy[u]=0;
    if (l==r)  {
        w[u]=a[l];
        return;
    }
    int mid=(l+r)/2;
    build(u*2,l,mid); build(u*2+1,mid+1,r);
    pushup(u);
}
bool inrange(int L,int R,int l,int r) {
    //[L,R]是否被[l,r]包含
    return l<=R&&L<=l;
}
bool outofrange(int L,int R,int l,int r) {
    //[L,R]是否和[l,r]完全无交
    return L>r||R<l;
}
void maketag(int u,int l,int r,ll x) {
    lazy[u]+=x;
    w[u]+=x*(r-l+1);
}
void pushdown(int u,int l,int r) {
    int mid=(l+r)/2;
    maketag(u*2,l,mid,lazy[u]);
    maketag(u*2+1,mid+1,r,lazy[u]);
    lazy[u]=0;
}
ll query(int u,int L,int R,int l,int r) { // 区间查询
    if (inrange(L,R,l,r)) {
        return w[u];
    } else if (!outofrange(L,R,l,r)) {
        int mid=(L+R)/2;
        pushdown(u,L,R);
        return query(u*2,L,mid,l,r)+query(u*2+1,mid+1,R,l,r);
    } else {
        return 0;
    }
}
void update(int u,int L,int R,int l,int r,ll x) { // 区间修改
    if (inrange(L,R,l,r)) {
        maketag(u,L,R,x);
    } else if (!outofrange(L,R,l,r)) {
        int mid=(L+R)/2;
        pushdown(u,L,R);
        update(u*2,L,mid,l,r,x);
        update(u*2+1,mid+1,R,l,r,x);
        pushup(u);
    }
}
int main() {
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(1,1,n);
    while (m--) {
        int op,x,y; ll k;
        scanf("%d",&op);
        if (op==1) {
            scanf("%d%d%lld",&x,&y,&k);
            update(1,1,n,x,y,k);
        } else {
            scanf("%d%d",&x,&y);
            printf("%lld\n",query(1,1,n,x,y));
        }
    }
    return 0;
}
2022/8/10 20:46
加载中...