线段树

点修改
Update(x,v): 把Ax修改为v
Query(L,R): 计算Min{AL,AL+1,...,AR}
minv[o]表示节点o所对应的区间中所有元素的最小值

int ql, qr; //查询[ql, qr]中的最小值
int query(int o, int L, int R){
    int M = L + (R-L)/2, ans = INF;
    if(ql <= L && qr >= R) return minv[o];
    if(ql <= M) ans = min(ans, query(2*o, L, M));
    if(qr > M) ans = min(ans, query(2*o+1, M+1, R));
    return ans;
}

int p, v; //修改: A[p] = v;
void update(int o, int L, int R){
    int M = L + (R - L)/2;
    if(L == R) minv[o] = v;
    else{
        if(p <= M) update(2*o, L, M);else update(2*o+1, M+1, R);
        minv[o] = min(minv[2*o], min[2*o+1]);
    }
}

区间修改
Add(L, R, v): 把AL, AL+1, ..., AR的值全部增加v
Query(L, R): 计算子序列AL,AL+1, ...,AR的元素和、最小值和最大值
sum[o]表示“如果只执行节点o及其子孙节点中的add操作,结点o对应区间中所有数之和”

//修改/查询范围均为[y1, y2]

void maintain(int o, int L, int R){
    int lc = 2*o, int lr = 2*o+1;
    sumv[o] = minv[o] = maxv[o] = 0;
    if(R > L){
        sumv[o] = sumv[lc] + sumv[lr];
        minv[o] = min(minv[lc], minv[rc]);
        maxv[o] = max(maxv[lc], maxv[rc]);
    }
    minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * (R-L+1);
}

void update(int o, int L, int R){
    int lc = 2*o, rc = 2*o+1;
    if(y1 <= L && y2 >= R){
        addv[o] += v;
    } else {
        int M = L + (R - L)/2;
        if(y1 <= M) update(lc, L, M);
        if(y2 > M) update(rc, M+1, R);
    }
    maintain(o, L, R);
}

//查询
int _min, _max, _sum;
void query(int o, int L, int R, int add) {
    if(y1 <= L && y2 >= R){
        _sum += sumv[o] + add * (R-L+1);
        _min = min(_min, minv[o] + add);
        _max = max(_max, maxv[o] + add);
    } else {
        int M = L + (R - L)/2;
        if(y1 <= M) query(2*o, L, M, add + addv[o]);
        if(y2 > M) query(2*o+1, M+1, R, add + addv[o]);
    }
}

快速序列操作
Set(L, R, v): 把AL, AL+1, ..., AR的值全部修改为v (v>=0)
Query(L, R): 计算子序列AL, AL+1, ..., AR的元素和、最小值和最大值

void pushdown(int o){
    int lc = 2*o, rc = 2*o+1;
    if(setv[o] >= 0) {
        set[lc] = set[rc] = setv[o];
        setv[o] = -1;
    }
}

void update(int o, int L, int R) {
    int lc = 2*o, rc = 2*o+1;
    if(y1 <= L && y2 >= R) {
        setv[o] = v;
    } else {
        pushdown(o);
        int M = L + (R - L)/2;
        if(y1 <= M) update(lc, L, M); else maintain(lc, L, M);
        if(y2 > M) update(rc, M+1, R); else maintain(rc, M+1, R);
    }
    maintain(o, L, R);
}

void query(int o, int L, int R){
    if(setv[o] >= 0) {
        _sum += setv[o] * (min(R, y2) - max(L, y1) + 1);
        _min = min(_min, setv[o]);
        _max = max(_max, setv[o]);
    } else if(y1 <= L && y2 >= R) {
        _sum += sumv[o];
        _min = min(_min, minv[o]);
        _max = max(_max, maxv[o]);
    } else {
        int M = L + (R - L)/2;
        if(y1 <= M) query(2*o, L, M);
        if(y2 > M) query(2*o+1, M+1, R);
    }
}

 

posted @ 2019-06-11 11:24  Hanasaki  阅读(128)  评论(0)    收藏  举报