标签:计算 序列 范围 inf ret 最小值 执行 区间 最大
点修改
Update(x,v): 吧Ax修改为v
Query(L,R): 计算{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); } }
标签:计算 序列 范围 inf ret 最小值 执行 区间 最大
原文地址:https://www.cnblogs.com/hanasaki/p/11002554.html