SPOJ - GSS1&&GSS3

GSS1

#include<cstdio>
#include<iostream>
#define lc k<<1
#define rc k<<1|1
using namespace std;
const int M=1e5+5,N=M<<2;
struct sgt{
    int sum,gss,lgss,rgss;
}tr[N];
int n,m,a[N];
void updata(int k){
    tr[k].sum=tr[lc].sum+tr[rc].sum;
    tr[k].lgss=max(tr[lc].lgss,tr[lc].sum+tr[rc].lgss);
    tr[k].rgss=max(tr[rc].rgss,tr[rc].sum+tr[lc].rgss);
    tr[k].gss=max(max(tr[lc].gss,tr[rc].gss),tr[lc].rgss+tr[rc].lgss);
}
void build(int k,int l,int r){
    if(l==r){
        tr[k].sum=tr[k].gss=tr[k].lgss=tr[k].rgss=a[l];
        return ;
    }
    int mid=l+r>>1;
    build(lc,l,mid);
    build(rc,mid+1,r);
    updata(k);
}
sgt query(int k,int l,int r,int x,int y){
    if(l==x&&r==y) return tr[k];
    int mid=l+r>>1;
    if(y<=mid) return query(lc,l,mid,x,y);
    else if(x>mid) return query(rc,mid+1,r,x,y);
    else{
        sgt left,right,result;
        left=query(lc,l,mid,x,mid);
        right=query(rc,mid+1,r,mid+1,y);
        result.sum=left.sum+right.sum;
        result.lgss=max(left.lgss,left.sum+right.lgss);
        result.rgss=max(right.rgss,right.sum+left.rgss);
        result.gss=max(max(left.gss,right.gss),left.rgss+right.lgss);
        return result;
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    build(1,1,n);
    scanf("%d",&m);
    for(int i=1,x,y;i<=m;i++){
        scanf("%d%d",&x,&y);
        printf("%d\n",query(1,1,n,x,y).gss);
    }
    return 0;
}

GSS3

#include<cstdio>
#include<iostream>
#define lc k<<1
#define rc k<<1|1
using namespace std;
const int M=1e5+5,N=M<<2;
struct sgtment{
    int sum,gss,lgss,rgss;
}tr[N];
int n,m,a[N];
void updata(int k){
    tr[k].sum=tr[lc].sum+tr[rc].sum;
    tr[k].lgss=max(tr[lc].lgss,tr[lc].sum+tr[rc].lgss);
    tr[k].rgss=max(tr[rc].rgss,tr[rc].sum+tr[lc].rgss);
    tr[k].gss=max(max(tr[lc].gss,tr[rc].gss),tr[lc].rgss+tr[rc].lgss);
}
void build(int k,int l,int r){
    if(l==r){
        tr[k].sum=tr[k].gss=tr[k].lgss=tr[k].rgss=a[l];
        return ;
    }
    int mid=l+r>>1;
    build(lc,l,mid);
    build(rc,mid+1,r);
    updata(k);
}
void change(int k,int l,int r,int pos,int val){
    if(l==r){
        tr[k].sum=tr[k].gss=tr[k].lgss=tr[k].rgss=val;
        return ;
    }
    int mid=l+r>>1;
    if(pos<=mid) change(lc,l,mid,pos,val);
    else change(rc,mid+1,r,pos,val);
    updata(k);
}
sgtment query(int k,int l,int r,int x,int y){
    if(l==x&&r==y) return tr[k];
    int mid=l+r>>1;
    if(y<=mid) return query(lc,l,mid,x,y);
    else if(x>mid) return query(rc,mid+1,r,x,y);
    else{
        sgtment left,right,result;
        left=query(lc,l,mid,x,mid);
        right=query(rc,mid+1,r,mid+1,y);
        result.sum=left.sum+right.sum;
        result.lgss=max(left.lgss,left.sum+right.lgss);
        result.rgss=max(right.rgss,right.sum+left.rgss);
        result.gss=max(max(left.gss,right.gss),left.rgss+right.lgss);
        return result;
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    build(1,1,n);
    scanf("%d",&m);
    for(int i=1,opt,x,y;i<=m;i++){
        scanf("%d%d%d",&opt,&x,&y);
        if(opt) printf("%d\n",query(1,1,n,x,y).gss);
        else change(1,1,n,x,y);
    }
    return 0;
}
时间: 2024-10-14 02:10:16

SPOJ - GSS1&&GSS3的相关文章

SPOJ GSS1 Can you answer these queries I

Can you answer these queries I Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: GSS164-bit integer IO format: %lld      Java class name: Main You are given a sequence $A[1], A[2], ..., A[N] $. $( |A[i]| \leq

SPOJ GSS1 静态区间求解最大子段和

题目大意: 给定n个数,再给q个区间询问,希望在区间s,t中找到一段连续的子序列使其和最大 因为询问上万,节点数50000,明显是用线段树去做,这里很明显的区间更新,唯一写起来有点恶心的是询问 每一个区间的最大都要跟左右区间的左最大右最大有关系 反正时要注意细节了,查询的时候同时要查询其左右连续最大 自己的错误在于左右连续最大的更新出问题,这个希望自己以后要注意 1 #include <cstdio> 2 #include <cstring> 3 #include <iost

Can you answer these queries I SPOJ - GSS1 (线段树维护区间连续最大值/最大连续子段和)

You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A query is defined as follows: Query(x,y) = Max { a[i]+a[i+1]+...+a[j] ; x ≤ i ≤ j ≤ y }. Given M queries, your program must output the results of these queries. Inp

浅谈线段树

 数据结构——线段树 O.引例 A.给出n个数,n<=100,和m个询问,每次询问区间[l,r]的和,并输出. 一种回答:这也太简单了,O(n)枚举搜索就行了. 另一种回答:还用得着o(n)枚举,前缀和o(1)就搞定. 那好,我再修改一下题目. B.给出n个数,n<=100,和m个操作,每个操作可能有两种:1.在某个位置加上一个数:2.询问区间[l,r]的和,并输出. 回答:o(n)枚举. 动态修改最起码不能用静态的前缀和做了. 好,我再修改题目: C.给出n个数,n<=1000000,

线段树讲解(转)

转自   http://www.cnblogs.com/TheRoadToTheGold/p/6254255.html  数据结构——线段树 O.引例 A.给出n个数,n<=100,和m个询问,每次询问区间[l,r]的和,并输出. 一种回答:这也太简单了,O(n)枚举搜索就行了. 另一种回答:还用得着o(n)枚举,前缀和o(1)就搞定. 那好,我再修改一下题目. B.给出n个数,n<=100,和m个操作,每个操作可能有两种:1.在某个位置加上一个数:2.询问区间[l,r]的和,并输出. 回答:

转自大佬的线段树

结构——线段树 O.引例 A.给出n个数,n<=100,和m个询问,每次询问区间[l,r]的和,并输出. 一种回答:这也太简单了,O(n)枚举搜索就行了. 另一种回答:还用得着o(n)枚举,前缀和o(1)就搞定. 那好,我再修改一下题目. B.给出n个数,n<=100,和m个操作,每个操作可能有两种:1.在某个位置加上一个数:2.询问区间[l,r]的和,并输出. 回答:o(n)枚举. 动态修改最起码不能用静态的前缀和做了. 好,我再修改题目: C.给出n个数,n<=1000000,和m个

SPOJ GSS系列 最大子段和 线段树+树链剖分+splay 1043 1557 1716 2713 2916 4487 6779

最大子段和的各种形式 题解内附每道题的 题意 题目链接 思路 SPOJ 1043 GSS1 静态区间求个最大子段和, 题解 SPOJ 1577 GSS2 和1一样,区别是若区间内存在相同的元素,则该元素只计算一次. 离线一下然后使劲跑.. 题解 SPOJ 1716 GSS3 和1一样,就是要支持单点修改 题解 SPOJ 2713 GSS4 ==普通线段树,感觉和这系列关系不大. 题解 SPOJ 2916 GSS5 题意有点怪,,跟3差不多,就是稍加强了点询问 题解 SPOJ 4487 GSS6

【SPOJ GSS】数据结构套题

SPOJ GSS1 题意:给一个序列以及一些询问,每个是问\([l,r]\)中最大连续子序列和是多少. 思路:这个问题是以下问题的基础. 我们考虑用线段树来解决这个问题. 首先我们来想想如果要求出最大连续子序列和需要什么信息. 对于\([l,m)\)和\([m,r)\)这两个区间,我们需要将它们合并成\([l,r)\)这个区间. 那么我们考虑分治地来解决这个问题.把问题分成三部分: \([l,m)\)中的最大子序列和 \([m,r)\)中的最大子序列和 左端点在\([l,m)\)内,右端点在\(

Oyk的ACM刷题记录(始于2015年2月29日,可能含剧透)

Online Judge 题目序号/题目 简单大意/题解 犯2情况 2月29日 SPOJ GSS1  不带更新区间最大子段和. 线段树维护 区间从左/右开始的最大值.区间最大值.区间和. 1.输出忘了换行. 2.打错了一个字母. SPOJ GSS2 区间不重复最大子段和. 离线维护s[i..now],线段树维护 区间历史最大值.区间历史最大更新值.区间现在最大值.区间现在更新值. 询问输出区间历史最大值. 1.线段树询问忘记写pushdown了. SPOJ TEST 输出所有42前的数. 1.不