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

 题目大意:

给定n个数,再给q个区间询问,希望在区间s,t中找到一段连续的子序列使其和最大

 

因为询问上万,节点数50000,明显是用线段树去做,这里很明显的区间更新,唯一写起来有点恶心的是询问

每一个区间的最大都要跟左右区间的左最大右最大有关系

反正时要注意细节了,查询的时候同时要查询其左右连续最大

 

自己的错误在于左右连续最大的更新出问题,这个希望自己以后要注意

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <set>
 6 #include <map>
 7 using namespace std;
 8 
 9 const int INF = 0x3fffffff;
10 #define N 50010
11 #define MOD 100007
12 #define ls o<<1
13 #define rs o<<1|1
14 #define define_m int m=(l+r)>>1
15 
16 int ml[N*3] , mr[N*3] , mx[N*3] , sum[N*3];
17 int a[N] , pre[N] , n;
18 
19 void push_up(int o)
20 {
21     mx[o] = max(mx[ls] , mx[rs]);
22     mx[o] = max(mx[o] , ml[rs]+mr[ls]);
23     ml[o] = max(ml[ls],sum[ls]+ml[rs]) , mr[o] = max(mr[rs],sum[rs]+mr[ls]);
24     sum[o] = sum[ls]+sum[rs];
25 }
26 
27 void build(int o , int l , int r)
28 {
29     if(l==r){
30         sum[o]=ml[o]=mr[o]=mx[o]=a[l];
31         return;
32     }
33     define_m;
34     build(ls , l , m);
35     build(rs , m+1 , r);
36     push_up(o);
37 }
38 
39 void query(int o , int l , int r , int s , int t , int &ansl , int &ansr , int &ans)
40 {
41     if(l>=s && r<=t){
42         ans = mx[o];
43         ansl = ml[o];
44         ansr = mr[o];
45         return ;
46     }
47     define_m;
48     if(m>=t) query(ls , l , m , s , t , ansl , ansr , ans);
49     else if(m<s) query(rs , m+1 , r , s , t , ansl , ansr ,ans);
50     else{
51         int t1,t2,t3,t4,t5,t6;
52         query(ls , l , m , s , m , t1 , t2 , t3);
53         query(rs , m+1 , r , m+1 , t , t4 , t5 , t6);
54         ansl = max(t1 , pre[m]-pre[s-1]+t4) , ansr = max(t5 , pre[t]-pre[m]+t2);
55         ans = max(t3 , t6);
56         ans = max(ans , t2+t4);
57     }
58     //cout<<o<<" "<<l<<" "<<r<<" "<<s<<" "<<t<<" "<<ansl<<" "<<ansr<<" "<<ans<<endl;
59 }
60 
61 int main()
62 {
63     #ifndef ONLINE_JUDGE
64         freopen("a.in" , "r" , stdin);
65     #endif // ONLINE_JUDGE
66     while(~scanf("%d" , &n))
67     {
68         for(int i=1 ; i<=n ; i++){
69             scanf("%d" , a+i);
70             pre[i] = pre[i-1]+a[i];
71         }
72         build(1 , 1 , n);
73         int m;
74         scanf("%d" , &m);
75         for(int i=0 ; i<m ; i++){
76             int s , t;
77             scanf("%d%d" , &s , &t);
78             int t1,t2,t3;
79             query(1,1,n,s,t,t1,t2,t3);
80             printf("%d\n" , t3);
81         }
82     }
83     return 0;
84 }

 

转载于:https://www.cnblogs.com/CSU3901130321/p/4557228.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值