您的位置:首页 > 其它

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函数会很难写。

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: