这个系列总共有7道题,目前只做了3道,gss2比较难,gss4是暴力修改,树状数组维护,还没写,gss6和gss7还不在能力范围内。
SPOJ_1043 GSS1
题意:给定长度不超过5万的序列,M次查询(貌似没给大小?。。),查询所给区间内的最大子段和。
做法:线段树。维护区间和sum,区间可以得到的最大值smax,从区间最左边开始的最大和lmax和右边开始的rmax,然后就可以了。具体更新还是看代码吧。比较巧妙的在于,把query函数的类型设为线段树的节点类型,这样就可以把它的子区间用update(即pushup)的操作来合并,否则query函数会很难写。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 int n, m; 5 int a[50100]; 6 struct tree{ 7 int sum, lmax, rmax, smax; 8 } t[50010 << 2]; 9 10 int max(int a, int b) 11 { 12 return a>b?a:b; 13 } 14 void update(tree &x, tree lson, tree rson) 15 { 16 x.sum = lson.sum + rson.sum; 17 x.lmax = max(lson.lmax, lson.sum+rson.lmax); 18 x.rmax = max(rson.rmax, rson.sum+lson.rmax); 19 int tmp = max(x.lmax, x.rmax); 20 tmp = max(tmp, x.sum); 21 tmp = max(tmp, lson.smax); 22 tmp = max(tmp, rson.smax); 23 tmp = max(tmp, lson.rmax+rson.lmax); 24 x.smax = tmp; 25 //x.smax = max(max(x.sum, max(x.lmax, x.rmax)), max(max((lson.smax, rson.smax), (lson.rmax+rson.lmax)))); 26 } 27 void build(int x, int l, int r) 28 { 29 if (l == r){ 30 t[x].sum = t[x].lmax = t[x].rmax = t[x].smax = a[l]; 31 return; 32 } 33 int mid = l + r >> 1, lson = x<<1, rson = x<<1|1; 34 build(lson, l, mid); 35 build(rson, mid+1, r); 36 update(t[x], t[lson], t[rson]); 37 } 38 tree query(int s, int e, int x, int l, int r) 39 { 40 if (s <= l && r <= e){ 41 //if (s <= l && r <= e){ 42 return t[x]; 43 } 44 int mid = l + r >> 1; 45 if (e <= mid) return query(s, e, x<<1, l, mid); 46 if (s > mid) return query(s, e, x<<1|1, mid+1, r); 47 tree p, q, ans; 48 p = query(s, mid, x<<1, l, mid); 49 q = query(mid+1, e, x<<1|1, mid+1, r); 50 update(ans, p, q); 51 return ans; 52 } 53 int main() 54 { 55 scanf("%d", &n); 56 for (int i = 1; i <= n; i++) 57 scanf("%d", &a[i]); 58 build(1, 1, n); 59 60 // for (int i = 1; i <= 10; i++) 61 // printf("%d %d %d %d %d\n", i, t[i].sum, t[i].lmax, t[i].rmax, t[i].smax); 62 63 scanf("%d", &m); 64 int x, y; 65 for (int i = 0; i < m; i++){ 66 scanf("%d %d", &x, &y); 67 printf("%d\n", query(x, y, 1, 1, n).smax); 68 } 69 return 0; 70 }
SPOJ_1557 GSS2
SPOJ_1716 GSS3
分析:相比gss1,多了一个单点修改的操作。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 int n, m; 5 int a[50100]; 6 struct tree{ 7 int sum, lmax, rmax, smax; 8 } t[50010 << 2]; 9 10 int max(int a, int b) 11 { 12 return a>b?a:b; 13 } 14 void pushup(tree &x, tree lson, tree rson) 15 { 16 x.sum = lson.sum + rson.sum; 17 x.lmax = max(lson.lmax, lson.sum+rson.lmax); 18 x.rmax = max(rson.rmax, rson.sum+lson.rmax); 19 /* int tmp = max(x.lmax, x.rmax); 20 tmp = max(tmp, x.sum); 21 tmp = max(tmp, lson.smax); 22 tmp = max(tmp, rson.smax); 23 */ 24 int tmp = max(lson.smax, rson.smax); 25 tmp = max(tmp, lson.rmax+rson.lmax); 26 x.smax = tmp; 27 } 28 void build(int x, int l, int r) 29 { 30 if (l == r){ 31 t[x].sum = t[x].lmax = t[x].rmax = t[x].smax = a[l]; 32 return; 33 } 34 int mid = l + r >> 1, lson = x<<1, rson = x<<1|1; 35 build(lson, l, mid); 36 build(rson, mid+1, r); 37 pushup(t[x], t[lson], t[rson]); 38 } 39 void update(int x, int l, int r, int p, int d) 40 { 41 if (l == r){ 42 t[x].sum = t[x].lmax = t[x].rmax = t[x].smax = d; 43 return; 44 } 45 int mid = l + r >> 1; 46 if (p <= mid) update(x<<1, l, mid, p, d); 47 if (p > mid) update(x<<1|1, mid+1, r, p, d); 48 pushup(t[x], t[x<<1], t[x<<1|1]); 49 } 50 tree query(int s, int e, int x, int l, int r) 51 { 52 if (s <= l && r <= e){ 53 return t[x]; 54 } 55 int mid = l + r >> 1; 56 if (e <= mid) return query(s, e, x<<1, l, mid); 57 if (s > mid) return query(s, e, x<<1|1, mid+1, r); 58 tree p, q, ans; 59 p = query(s, mid, x<<1, l, mid); 60 q = query(mid+1, e, x<<1|1, mid+1, r); 61 pushup(ans, p, q); 62 return ans; 63 } 64 int main() 65 { 66 scanf("%d", &n); 67 for (int i = 1; i <= n; i++) 68 scanf("%d", &a[i]); 69 build(1, 1, n); 70 scanf("%d", &m); 71 int q, x, y; 72 for (int i = 0; i < m; i++){ 73 scanf("%d %d %d", &q, &x, &y); 74 if (q == 1) 75 printf("%d\n", query(x, y, 1, 1, n).smax); 76 else 77 update(1, 1, n, x, y); 78 } 79 return 0; 80 }
SPOJ_2713 GSS4
SPOJ_2916 GSS5
分析:相比gss1,查询变成对左端点和右端点的不同区间限制,耐心地分类讨论就可以了。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 int n, m; 5 int a[10100], sum[10100]; 6 struct tree{ 7 int sum, lmax, rmax, smax; 8 } t[10100 << 2]; 9 10 int max(int a, int b) 11 { 12 return a>b?a:b; 13 } 14 void update(tree &x, tree lson, tree rson) 15 { 16 x.sum = lson.sum + rson.sum; 17 x.lmax = max(lson.lmax, lson.sum+rson.lmax); 18 x.rmax = max(rson.rmax, rson.sum+lson.rmax); 19 int tmp = max(lson.smax, rson.smax); 20 tmp = max(tmp, lson.rmax+rson.lmax); 21 x.smax = tmp; 22 } 23 void build(int x, int l, int r) 24 { 25 if (l == r){ 26 t[x].sum = t[x].lmax = t[x].rmax = t[x].smax = a[l]; 27 return; 28 } 29 int mid = l + r >> 1, lson = x<<1, rson = x<<1|1; 30 build(lson, l, mid); 31 build(rson, mid+1, r); 32 update(t[x], t[lson], t[rson]); 33 } 34 tree query(int s, int e, int x, int l, int r) 35 { 36 if (s <= l && r <= e){ 37 return t[x]; 38 } 39 int mid = l + r >> 1; 40 if (e <= mid) return query(s, e, x<<1, l, mid); 41 if (s > mid) return query(s, e, x<<1|1, mid+1, r); 42 tree p, q, ans; 43 p = query(s, mid, x<<1, l, mid); 44 q = query(mid+1, e, x<<1|1, mid+1, r); 45 update(ans, p, q); 46 return ans; 47 } 48 int main() 49 { 50 int T; 51 scanf("%d", &T); 52 while(T--) 53 { 54 scanf("%d", &n); 55 for (int i = 1; i <= n; i++) 56 scanf("%d", &a[i]); 57 sum[0] = 0; 58 for (int i = 1; i <= n; i++) 59 sum[i] = sum[i-1] + a[i]; 60 build(1, 1, n); 61 scanf("%d", &m); 62 int x1, y1, x2, y2; 63 for (int i = 0; i < m; i++){ 64 scanf("%d %d %d %d", &x1, &y1, &x2, &y2); 65 int ans = 0; 66 if (y1 == x2){ 67 // ans = a[y1]; 68 // int tmp1 = 0, tmp2 = 0; 69 // if (x1 <= y1-1) tmp1 = max(query(x1, y1-1, 1, 1, n).rmax, 0); 70 // if (x2+1 <= y2) tmp2 = max(query(x2+1, y2, 1, 1, n).lmax, 0); 71 // ans += tmp1 + tmp2; 72 ans = query(x1, y1, 1, 1, n).rmax + query(x2, y2, 1, 1, n).lmax - a[y1]; 73 } 74 else if (y1 < x2){ 75 ans = sum[x2-1] - sum[y1]; 76 ans += query(x1, y1, 1, 1, n).rmax + query(x2, y2, 1, 1, n).lmax; 77 } 78 else{ 79 int tmp = query(x2, y1, 1, 1, n).smax; 80 ans = tmp; 81 82 tmp = sum[y1-1] - sum[x2]; 83 tmp += query(x1, x2, 1, 1, n).rmax + query(y1, y2, 1, 1, n).lmax; 84 ans = max(tmp, ans); 85 86 tmp = query(x1, x2, 1, 1, n).rmax + query(x2, y1, 1, 1, n).lmax - a[x2]; 87 ans = max(tmp, ans); 88 89 tmp = query(x2, y1, 1, 1, n).rmax + query(y1, y2, 1, 1, n).lmax - a[y1]; 90 ans = max(tmp, ans); 91 92 } 93 printf("%d\n", ans); 94 } 95 } 96 return 0; 97 }
SPOJ_4487 GSS6
SPOJ_6779 GSS7
SPOJ GSS系列 解题报告,布布扣,bubuko.com
时间: 2024-10-05 16:23:16