題目模型
問題分析
方法一:字首和
我們稍微修改一下**就可以解決最大子段和不能為空的問題
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,開頭的最大連續和,此時開頭已經確定了,那麼通過列舉...