P1115 最大子段和 分治
前言
最近听了去年提高组秋令营,听说一条普及- 的题目可以用到分治高级题目的做法,顺便看题解前面好像没有,于是就把我的第一次洛谷题解交给了她。。。
e.咳咳我们转入正题。
我们怎么用分治?
· 我们发现,如果由两个小区间合成一个大区间,答案可能在哪些地方呢?
-
是整个区间的前缀最大值
-
是整个区间的后缀最大值
-
是跨越中点的一段区间
-
原来是上面三种情况,但由于经过合并已经并到里面去的区间。(关于“里面”的解释)
这个4就是里面啦啦啦啦
所以,我们用一个结构体存下这所有东西先。。
struct xx{
int l,r,md,sum,ans;
xx(int ll,int rr,int m,int s,int a){
l=ll;r=rr;md=m;sum=s;ans=a;
}//ans是区间的答案,sum是区间总和便于下一步
};
然后对于每种答案型的继承
- 有我画的两种情况(绿色!)
max(t1.l,t1.sum+t2.l)
-
同理(雷姆蓝!)
-
黄色很好想吧
t1.r+t2.l
- 由于我们对每个区间都记录了最大值,继承子区间,并和新的区间参数比较
max(max(max(t3.l,t3.r),t3.md),max(t1.ans,t2.ans));
max打得我累死了呼呼
呦西,这样,一份超级简单的代码就新鲜出炉啦
//P1115 最大子段和分治
#include<iostream>
using namespace std;
#define N 200005
struct xx{
int l,r,md,sum,ans;
xx(int ll,int rr,int m,int s,int a){
l=ll;r=rr;md=m;sum=s;ans=a;
}
};
int n,a[N];
xx solve(int l,int r){
if(l==r)return xx(a[l],a[l],a[l],a[l],a[l]);
int md=(l+r)>>1;
xx t1=solve(l,md),t2=solve(md+1,r);
xx t3=xx(max(t1.l,t1.sum+t2.l),max(t2.r,t2.sum+t1.r),t1.r+t2.l,t1.sum+t2.sum,0);
t3.ans=max(max(max(t3.l,t3.r),t3.md),max(t1.ans,t2.ans));
return t3;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
xx ans=solve(1,n);
cout<<ans.ans<<endl;
return 217527; //反抄袭大法好并滑稽保命
}
//made by jiangji2
就这样吧,第一次写题解,谢谢您的耐心观看QWQ!