線段樹(2)區間修改
快速序列操作I,給出一個n個元素的數組A1,A2,…,An,你的任務是設計一個數據結構支持一下兩種操作
set(L, R, v): 把AL,AL+1,…,Ar的值全部修改爲v(v>=0)
Query(L, R):計算子序列AL,AL+1,…Ar的元素和、最小值和最大值。
#include <cstdio>
#include <algorithm>
using namespace std;
#define LL(x) x<<1
#define RR(x) x<<1|1
typedef long long INT;
const int maxn = 500;
INT setv[maxn<<2] = {-1}, minv[maxn<<2], maxv[maxn<<2], sumv[maxn<<2], a[maxn<<2];
INT _min, _max, _sum, v;
int y1, y2;
void BuildTree(int L, int R, int o) {
if (L == R) {
maxv[o] = minv[o] = sumv[o] = a[L];
} else {
int mid = (L+R)/2;
int lc = LL(o);
int rc = RR(o);
BuildTree(L, mid, lc);
BuildTree(mid+1, R, rc);
maxv[o] = max(maxv[lc], maxv[rc]);
minv[o] = min(minv[lc], minv[rc]);
sumv[o] = sumv[lc] + sumv[rc];
}
}
void maintain(int l, int r, int o) {
if (setv[o] >= 0) {
maxv[o] = setv[o];
minv[o] = setv[o];
sumv[o] = setv[o] * (r-l+1);
} else if (l < r) {
int lc = LL(o);
int rc = RR(o);
sumv[o] = sumv[lc] + sumv[rc];
maxv[o] = max(maxv[lc], maxv[rc]);
minv[o] = min(minv[lc], minv[rc]);
}
}
void pushdown(int o) {
int lc = LL(o);
int rc = RR(o);
if (setv[o] >= 0) {
setv[lc] = setv[rc] = setv[o];
setv[o] = -1;
}
}
void update(int l, int r, int o) {
if (y1 <= l && y2 >= r) {
setv[o] = v;
} else {
pushdown(o);
int m = (l+r)/2;
if (y1 <= m) {
update(l, m, o*2);
} else {
maintain(l, m, o*2);
}
if (y2 > m) {
update(m+1, r, o*2+1);
} else {
maintain(m+1, r, o*2+1);
}
}
maintain(l, r, o);
}
void Query(int L, int R, int o) {
if (setv[o] >= 0) {
_sum += setv[o]*(min(R,y2)-max(y1,L)+1); //BUG
_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)/2;
if (y1 <= m) Query(L, m, o*2);
if (y2 > m) Query(m+1, R, o*2+1);
}
}