CST2018 3-1-1 Sum (15%)
简单的线段树,单点修改,区间求和。
很简单。
CST2018 3-1-2 Max (20%)
高级的线段树。
维护区间最大和,区间和,左边最大和,右边最大和。
单点修改的时候一路吧区间都改了就好了。
求子段最大值也就判断一下左右就好了。
略微复杂。
1 #include <cstdio> 2 3 using namespace std; 4 const int N = 5e5 + 5; 5 const int inf = 1e9; 6 int n, m; 7 int a[N]; 8 9 inline int max(int x, int y) { 10 return x > y ? x : y; 11 } 12 13 struct seg { 14 seg *ls, *rs; 15 int sum, mx, mxl, mxr; 16 17 void* operator new(size_t) { 18 static seg* c; 19 c = new seg[1]; 20 c -> ls = c -> rs = NULL; 21 c -> mxl = c -> mxr = c -> mx = c -> sum = 0; 22 return c; 23 } 24 25 inline void change_point(int x) { //change the value of a single point 26 if (x > 0) { 27 sum = mx = mxl = mxr = x; 28 } else { 29 sum = x; 30 mx = mxl = mxr = 0; 31 } 32 } 33 34 inline void update() { 35 if (ls == NULL || rs == NULL) return; 36 sum = ls -> sum + rs -> sum; 37 mx = max(max(ls -> mx, rs -> mx), ls -> mxr + rs -> mxl); 38 mxl = max(ls -> mxl, ls -> sum + rs -> mxl); 39 mxr = max(rs -> mxr, rs -> sum + ls -> mxr); 40 } 41 42 #define mid (l + r >> 1) 43 void build(int l, int r) { 44 if (l == r) { 45 change_point(a[l]); 46 return; 47 } 48 ls = new()seg, ls -> build(l, mid); 49 rs = new()seg, rs -> build(mid + 1, r); 50 update(); 51 } 52 53 void modify(int l, int r, int pos, int x) { 54 if (pos < l || r < pos) return; 55 if (l == r) { 56 change_point(x); 57 return; 58 } 59 if (pos <= mid) ls -> modify(l, mid, pos, x); 60 if (mid < pos) rs -> modify(mid + 1 , r, pos, x); 61 update(); 62 } 63 64 seg* query(int l, int r, int L, int R) { 65 seg* ret = new()seg; 66 if (l == L && R == r) { 67 *ret = *this; 68 return ret; 69 } 70 if (R <= mid) return ls -> query(l, mid, L, R); 71 if (L > mid) return rs -> query(mid + 1, r, L, R); 72 73 ret -> ls = ls -> query(l, mid, L, mid); 74 ret -> rs = rs -> query(mid + 1, r, mid + 1, R); 75 ret -> update(); 76 delete ret -> ls; 77 delete ret -> rs; 78 return ret; 79 } 80 #undef mid 81 } *segment, *ans; 82 83 int main() { 84 int op, x, y; 85 scanf("%d%d", &n, &m); 86 for (int i = 1; i <= n; ++i) 87 scanf("%d", a + i); 88 segment = new()seg; 89 segment -> build(1, n); 90 for (int i = 1; i <= m; ++i) { 91 scanf("%d%d%d", &op, &x, &y); 92 if (op == 0) { 93 segment -> modify(1, n, x, y); 94 } else { 95 ans = segment -> query(1, n, x, y); 96 printf("%d\n", ans -> mx); 97 delete ans; 98 } 99 } 100 return 0; 101 }