SPOJ GSS系列 解题报告
2014-07-27 21:29
423 查看
这个系列总共有7道题,目前只做了3道,gss2比较难,gss4是暴力修改,树状数组维护,还没写,gss6和gss7还不在能力范围内。
SPOJ_1043 GSS1
题意:给定长度不超过5万的序列,M次查询(貌似没给大小?。。),查询所给区间内的最大子段和。
做法:线段树。维护区间和sum,区间可以得到的最大值smax,从区间最左边开始的最大和lmax和右边开始的rmax,然后就可以了。具体更新还是看代码吧。比较巧妙的在于,把query函数的类型设为线段树的节点类型,这样就可以把它的子区间用update(即pushup)的操作来合并,否则query函数会很难写。
SPOJ_1557 GSS2
SPOJ_1716 GSS3
分析:相比gss1,多了一个单点修改的操作。
SPOJ_2713 GSS4
SPOJ_2916 GSS5
分析:相比gss1,查询变成对左端点和右端点的不同区间限制,耐心地分类讨论就可以了。
SPOJ_4487 GSS6
SPOJ_6779 GSS7
SPOJ_1043 GSS1
题意:给定长度不超过5万的序列,M次查询(貌似没给大小?。。),查询所给区间内的最大子段和。
做法:线段树。维护区间和sum,区间可以得到的最大值smax,从区间最左边开始的最大和lmax和右边开始的rmax,然后就可以了。具体更新还是看代码吧。比较巧妙的在于,把query函数的类型设为线段树的节点类型,这样就可以把它的子区间用update(即pushup)的操作来合并,否则query函数会很难写。
#include<cstdio> #include<cstring> #include<algorithm> int n, m; int a[50100]; struct tree{ int sum, lmax, rmax, smax; } t[50010 << 2]; int max(int a, int b) { return a>b?a:b; } void update(tree &x, tree lson, tree rson) { x.sum = lson.sum + rson.sum; x.lmax = max(lson.lmax, lson.sum+rson.lmax); x.rmax = max(rson.rmax, rson.sum+lson.rmax); int tmp = max(x.lmax, x.rmax); tmp = max(tmp, x.sum); tmp = max(tmp, lson.smax); tmp = max(tmp, rson.smax); tmp = max(tmp, lson.rmax+rson.lmax); x.smax = tmp; //x.smax = max(max(x.sum, max(x.lmax, x.rmax)), max(max((lson.smax, rson.smax), (lson.rmax+rson.lmax)))); } void build(int x, int l, int r) { if (l == r){ t[x].sum = t[x].lmax = t[x].rmax = t[x].smax = a[l]; return; } int mid = l + r >> 1, lson = x<<1, rson = x<<1|1; build(lson, l, mid); build(rson, mid+1, r); update(t[x], t[lson], t[rson]); } tree query(int s, int e, int x, int l, int r) { if (s <= l && r <= e){ //if (s <= l && r <= e){ return t[x]; } int mid = l + r >> 1; if (e <= mid) return query(s, e, x<<1, l, mid); if (s > mid) return query(s, e, x<<1|1, mid+1, r); tree p, q, ans; p = query(s, mid, x<<1, l, mid); q = query(mid+1, e, x<<1|1, mid+1, r); update(ans, p, q); return ans; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); build(1, 1, n); // for (int i = 1; i <= 10; i++) // printf("%d %d %d %d %d\n", i, t[i].sum, t[i].lmax, t[i].rmax, t[i].smax); scanf("%d", &m); int x, y; for (int i = 0; i < m; i++){ scanf("%d %d", &x, &y); printf("%d\n", query(x, y, 1, 1, n).smax); } return 0; }
SPOJ_1557 GSS2
SPOJ_1716 GSS3
分析:相比gss1,多了一个单点修改的操作。
#include<cstdio> #include<cstring> #include<algorithm> int n, m; int a[50100]; struct tree{ int sum, lmax, rmax, smax; } t[50010 << 2]; int max(int a, int b) { return a>b?a:b; } void pushup(tree &x, tree lson, tree rson) { x.sum = lson.sum + rson.sum; x.lmax = max(lson.lmax, lson.sum+rson.lmax); x.rmax = max(rson.rmax, rson.sum+lson.rmax); /* int tmp = max(x.lmax, x.rmax); tmp = max(tmp, x.sum); tmp = max(tmp, lson.smax); tmp = max(tmp, rson.smax); */ int tmp = max(lson.smax, rson.smax); tmp = max(tmp, lson.rmax+rson.lmax); x.smax = tmp; } void build(int x, int l, int r) { if (l == r){ t[x].sum = t[x].lmax = t[x].rmax = t[x].smax = a[l]; return; } int mid = l + r >> 1, lson = x<<1, rson = x<<1|1; build(lson, l, mid); build(rson, mid+1, r); pushup(t[x], t[lson], t[rson]); } void update(int x, int l, int r, int p, int d) { if (l == r){ t[x].sum = t[x].lmax = t[x].rmax = t[x].smax = d; return; } int mid = l + r >> 1; if (p <= mid) update(x<<1, l, mid, p, d); if (p > mid) update(x<<1|1, mid+1, r, p, d); pushup(t[x], t[x<<1], t[x<<1|1]); } tree query(int s, int e, int x, int l, int r) { if (s <= l && r <= e){ return t[x]; } int mid = l + r >> 1; if (e <= mid) return query(s, e, x<<1, l, mid); if (s > mid) return query(s, e, x<<1|1, mid+1, r); tree p, q, ans; p = query(s, mid, x<<1, l, mid); q = query(mid+1, e, x<<1|1, mid+1, r); pushup(ans, p, q); return ans; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); build(1, 1, n); scanf("%d", &m); int q, x, y; for (int i = 0; i < m; i++){ scanf("%d %d %d", &q, &x, &y); if (q == 1) printf("%d\n", query(x, y, 1, 1, n).smax); else update(1, 1, n, x, y); } return 0; }
SPOJ_2713 GSS4
SPOJ_2916 GSS5
分析:相比gss1,查询变成对左端点和右端点的不同区间限制,耐心地分类讨论就可以了。
#include<cstdio> #include<cstring> #include<algorithm> int n, m; int a[10100], sum[10100]; struct tree{ int sum, lmax, rmax, smax; } t[10100 << 2]; int max(int a, int b) { return a>b?a:b; } void update(tree &x, tree lson, tree rson) { x.sum = lson.sum + rson.sum; x.lmax = max(lson.lmax, lson.sum+rson.lmax); x.rmax = max(rson.rmax, rson.sum+lson.rmax); int tmp = max(lson.smax, rson.smax); tmp = max(tmp, lson.rmax+rson.lmax); x.smax = tmp; } void build(int x, int l, int r) { if (l == r){ t[x].sum = t[x].lmax = t[x].rmax = t[x].smax = a[l]; return; } int mid = l + r >> 1, lson = x<<1, rson = x<<1|1; build(lson, l, mid); build(rson, mid+1, r); update(t[x], t[lson], t[rson]); } tree query(int s, int e, int x, int l, int r) { if (s <= l && r <= e){ return t[x]; } int mid = l + r >> 1; if (e <= mid) return query(s, e, x<<1, l, mid); if (s > mid) return query(s, e, x<<1|1, mid+1, r); tree p, q, ans; p = query(s, mid, x<<1, l, mid); q = query(mid+1, e, x<<1|1, mid+1, r); update(ans, p, q); return ans; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); sum[0] = 0; for (int i = 1; i <= n; i++) sum[i] = sum[i-1] + a[i]; build(1, 1, n); scanf("%d", &m); int x1, y1, x2, y2; for (int i = 0; i < m; i++){ scanf("%d %d %d %d", &x1, &y1, &x2, &y2); int ans = 0; if (y1 == x2){ // ans = a[y1]; // int tmp1 = 0, tmp2 = 0; // if (x1 <= y1-1) tmp1 = max(query(x1, y1-1, 1, 1, n).rmax, 0); // if (x2+1 <= y2) tmp2 = max(query(x2+1, y2, 1, 1, n).lmax, 0); // ans += tmp1 + tmp2; ans = query(x1, y1, 1, 1, n).rmax + query(x2, y2, 1, 1, n).lmax - a[y1]; } else if (y1 < x2){ ans = sum[x2-1] - sum[y1]; ans += query(x1, y1, 1, 1, n).rmax + query(x2, y2, 1, 1, n).lmax; } else{ int tmp = query(x2, y1, 1, 1, n).smax; ans = tmp; tmp = sum[y1-1] - sum[x2]; tmp += query(x1, x2, 1, 1, n).rmax + query(y1, y2, 1, 1, n).lmax; ans = max(tmp, ans); tmp = query(x1, x2, 1, 1, n).rmax + query(x2, y1, 1, 1, n).lmax - a[x2]; ans = max(tmp, ans); tmp = query(x2, y1, 1, 1, n).rmax + query(y1, y2, 1, 1, n).lmax - a[y1]; ans = max(tmp, ans); } printf("%d\n", ans); } } return 0; }
SPOJ_4487 GSS6
SPOJ_6779 GSS7
相关文章推荐
- [spoj10707]Count on a tree II 解题报告
- SPOJ 1771 Yet Another N-Queen Problem 解题报告(Dancing Link)
- [spoj244]Transposing is Even More Fun 解题报告
- Spoj数论专场解题报告
- HDU:1465不容易系列之一解题报告
- 【在线笔试题解题报告系列】微软在线笔试之 2016微软探星夏令营在线技术笔试(时间:2016.07.17)
- Spring-2-H Array Diversity(SPOJ AMR11H)解题报告及测试数据
- [SPOJ1043,1557,1716,2713,2916,4487,6779,19543]GSS八题系列
- ACdream区域赛指导赛之手速赛系列(5) 解题报告 A C D
- hdu 4527 小明系列故事——玩转十滴水 bfs 解题报告
- Find Minimum in Rotated Sorted Array系列解题报告
- hdu4528 小明系列故事——捉迷藏 解题报告
- SPOJ 694 后缀数组 解题报告
- spoj GSS系列之GSS1 和 GSS3
- hdoj 2042 不容易系列之二 解题报告 (老汉牵羊过收费站问题)(超水递推)
- (解题报告)HDU4513---吉哥系列故事之礼尚往来(错排)
- SPOJ QTREE 系列解题报告
- hdu 4544 湫湫系列故事——消灭兔子 贪心+优先队列 解题报告
- OrzFAng系列–树 解题报告
- hdoj 2045 不容易系列之(3)—— LELE的RPG难题 解题报告(简单递推)