最大子段和之基礎模型

2022-02-04 03:44:46 字數 3236 閱讀 8715

題目模型

問題分析

方法一:字首和

我們稍微修改一下**就可以解決最大子段和不能為空的問題

code

#includeusing namespace std;

typedef long long ll;

const int maxn=1e7+5,maxm=1e5+5;

const ll inf=0x3f3f3f3f3f3f3f3f;

ll a[maxn],sum[maxn];

int n;

void solve()

printf("%lld\n",ans);

}int main()

方法二:動態規劃

code

#includeusing namespace std;

typedef long long ll;

const int maxn=1e7+5,maxm=1e5+5;

const ll inf=0x3f3f3f3f3f3f3f3f;

ll f[maxn],a[maxn],ans;

int n;

void solve()

printf("%lld\n",ans);

}int main()

方法三:分治題目模型

問題分析

**實現

#includeusing namespace std;

typedef long long ll;

const int maxn=5e5+10;

#define lson l,mid,(rt<<1)

#define rson mid+1,r,(rt<<1|1)

struct treetree[maxn<<2];

tree pushup(tree l,tree r)

void build(int l,int r,int rt)

int mid=(l+r)>>1;

build(lson);

build(rson);

tree[rt]=pushup(tree[rt<<1],tree[rt<<1|1]);

}void update(int pos,int w,int l,int r,int rt)

int mid=(l+r)>>1;

if(pos<=mid) update(pos,w,lson);

if(pos> mid) update(pos,w,rson);

tree[rt]=pushup(tree[rt<<1],tree[rt<<1|1]);

}tree query(int l,int r,int l,int r,int rt)

if(r> mid)

if(flag1&&flag2) ret=pushup(lret,rret);//左右子樹均有就合併計算

else if(flag1) ret=lret;//只在左子樹

else if(flag2) ret=rret;//只在右子樹

return ret;

}void solve()

else

}}int main()

題目模型

問題分析

方法一:

最大和的這個子段包含了頭尾。

然後比較兩種情況的大小,輸出大的那乙個就行。

code

#include const int maxn = 1e7+5,inf=0x3f3f3f3f;

typedef long long ll;

ll a[maxn],b[maxn],dp[maxn];

ll sum = 0,max = 0,min = 0;

void solve()

for(int i=1;i<=n;++i)

memset(dp,0,sizeof(dp));

for(int i=1;i<=n;++i)

ll ans=std::max(max,sum+min);//sum+min相當於序列和減去最小區間和

printf("%lld\n",ans);

} int main()

方法二:題目模型

問題分析題目模型

問題分析

方法二

題目模型

問題分析

錯誤code

#include typedef long long ll;

const int maxn = 5e4+5;

const ll inf=0x3f3f3f3f3f3f3f3f;

ll a[maxn],dp1[maxn],dp2[maxn];//dp1[i]以a[i]結尾的最大子段和,dp2[i]表示以a[i]開始的最大子段和

ll l[maxn],r[maxn],lmax[maxn],rmax[maxn];//l[i]以a[i]結尾的最大子段和的左邊界,r[i]類似。

void solve()

else l[i]=-1;//dp1[i-1]+a[i]<=0就什麼都不選,為空

} rmax[n+1]=-inf; //如果a[n]為負,如果rmax[n+1]=0,那求出的rmax[n]=0,是錯誤的。

for(int i=n;i>0;--i)

else r[i]=-1;

}

ll ans=0;

l[0]=r[n+1]=-1;//0不存在左邊界,n+1不存在右邊界

for(int i=1;i<=n;++i)//如果存在以a[i-1]結尾的大於0最大子段和

if(r[i+1]!=-1)//如果存在以a[i+1]開始的大於0最大子段和

ans=std::max(ans,x+std::max(lmax[l-1],rmax[r+1]));

}printf("%lld\n",ans);

}int main()/*4

-2 -4 1 -1

上面**過不了下面的樣例

錯誤的願因是需要交換的a[i]向左擴充套件並不一定是包含a[i-1]的最大子段和

6100 -1 1 -10 1 1

*/

最大子段和

設a 是n個整數的序列,稱為該序列的子串行,其中1 i j n.子串行的元素之和稱為a的子段和.例如,a 2,11,4,13,5,2 那麼它的子段和是 長度為1的子段和 2,11,4,13,5,2 長度為2的子段和 9,7,9,8,7 長度為3的子段和 5,20,4,6 長度為4的子段和 18,15...

最大子段和

問題表述 n個數 可能是負數 組成的序列a1,a2,an.求該序列 例如 序列 2,11,4,13,5,2 最大子段和 11 4 13 20。1 窮舉演算法 o n3 o n2 2 分治法 將序列a 1 n 從n 2處截成兩段 a 1 n 2 a n 2 1 n 例項 三 最大子段和 問題表述 n個...

最大子段和

再給頂的n個數的陣列中選出連續的若干個數,使得他們的和是最大的,即最大連續自序列和.列如.序列.1 2 3 1 6 5 9 結果 當取子串行 3,1,6,5,9 結果12 我的思路.1.最大連續子串行的開頭是在1.n之中.的最大連續和 2.求出以i,開頭的最大連續和,此時開頭已經確定了,那麼通過列舉...