1 /* 2 maxnode为区间长度的三倍 3 调用: 4 tree.update(1, 1, n); 5 tree.query(1, 1, n, 0); 6 n为区间长度,[y11, y22]为维护或查询区间,v为增加值或修改值 7 op == 1时区间加上v,op == 2时区间修改为v 8 */ 9 const int maxnode = 100000 * 3; 10 int _sum, _min, _max, op, y11, y22, v; 11 struct IntervalTree { 12 int sumv[maxnode], minv[maxnode], maxv[maxnode], setv[maxnode], addv[maxnode]; 13 14 // 维护信息 15 void maintain(int o, int L, int R) { 16 int lc = o*2, rc = o*2+1; 17 if(R > L) { 18 sumv[o] = sumv[lc] + sumv[rc]; 19 minv[o] = min(minv[lc], minv[rc]); 20 maxv[o] = max(maxv[lc], maxv[rc]); 21 } 22 if(setv[o] >= 0) { minv[o] = maxv[o] = setv[o]; sumv[o] = setv[o] * (R-L+1); } 23 if(addv[o]) { minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += addv[o] * (R-L+1); } 24 } 25 26 // 标记传递 27 void unmark(int o) { 28 int lc = o*2, rc = o*2+1; 29 if(setv[o] >= 0) { 30 setv[lc] = setv[rc] = setv[o]; 31 addv[lc] = addv[rc] = 0; 32 setv[o] = -1; // 清除本结点标记 33 } 34 if(addv[o]) { 35 addv[lc] += addv[o]; 36 addv[rc] += addv[o]; 37 addv[o] = 0; // 清除本结点标记 38 } 39 } 40 41 void update(int o, int L, int R) { 42 int lc = o*2, rc = o*2+1; 43 if(y11 <= L && y22 >= R) { // 标记修改 44 if(op == 1) addv[o] += v; 45 else { setv[o] = v; addv[o] = 0; } 46 } else { 47 unmark(o); 48 int M = L + (R-L)/2; 49 if(y11 <= M) update(lc, L, M); else maintain(lc, L, M); 50 if(y22 > M) update(rc, M+1, R); else maintain(rc, M+1, R); 51 } 52 maintain(o, L, R); 53 } 54 55 void query(int o, int L, int R, int add) { 56 if(setv[o] >= 0) { 57 int v = setv[o] + add + addv[o]; 58 _sum += v * (min(R,y22)-max(L,y11)+1); 59 _min = min(_min, v); 60 _max = max(_max, v); 61 } else if(y11 <= L && y22 >= R) { 62 _sum += sumv[o] + add * (R-L+1); 63 _min = min(_min, minv[o] + add); 64 _max = max(_max, maxv[o] + add); 65 } else { 66 int M = L + (R-L)/2; 67 if(y11 <= M) query(o*2, L, M, add + addv[o]); 68 if(y22 > M) query(o*2+1, M+1, R, add + addv[o]); 69 } 70 } 71 } tree;