CDOJ 839 东风不与周郎便(线段树写法1)

题意:区间更新v,区间查询v

解法:线段树,只用两个数组,开4倍,不带懒操作的。。这题一年前已过,然发现主席树上不带懒操作的写法比带懒操作的在各个方面都要优越,并且发现线段树才是主席树的基础,线段树写美了,主席树也就美了,因此特记下此题,写下此文,以此谨记。

#include<cstdio>
typedef long long ll;

#define N 100010
#define lch id<<1
#define rch id<<1|1
int n, m;
ll v[N << 2], la[N << 2];

void plant(int id, int l, int r){
    la[id] = 0;
    if(l == r){
        scanf("%lld", v + id);
        return;
    }
    int mid = (l + r) >> 1;
    plant(lch, l, mid);
    plant(rch, mid + 1, r);
    v[id] = v[lch] + v[rch];
}
void update(int id, int ql, int qr, int l, int r, ll val){
    v[id] += (qr - ql + 1) * val;
    if(ql == l && qr == r){
        la[id] += val;
        return;
    }
    int mid = (l + r) >> 1;
    if(qr <= mid) update(lch, ql, qr, l, mid, val);
    else if(mid < ql) update(rch, ql, qr, mid + 1, r, val);
    else update(lch, ql, mid, l, mid, val), update(rch, mid + 1, qr, mid + 1, r, val);
}
ll query(int id, int ql, int qr, int l, int r){
    if(ql == l && qr == r) return v[id];
    int mid = (l + r) >> 1;
    ll ex = la[id] * (qr - ql + 1);
    if(qr <= mid) return ex + query(lch, ql, qr, l, mid);
    else if(mid < ql) return ex + query(rch, ql, qr, mid + 1, r);
    else return ex + query(lch, ql, mid, l, mid) + query(rch, mid + 1, qr, mid + 1, r);
}

int main(){
    scanf("%d%d",&n,&m);
    plant(1, 1, n);
    for(int i = 1; i <= m; i++){
        int ty, l, r;
        scanf("%d%d%d",&ty,&l,&r);
        if(ty == 0)
        {
            printf("%lld\n", query(1, l, r, 1, n));
        }
        else
        {
            int v;
            scanf("%d",&v);
            update(1, l, r, 1, n, v);
        }
    }
    return 0;
}

你可能感兴趣的:(CDOJ 839 东风不与周郎便(线段树写法1))