最大子段和之可交換

2022-02-04 03:44:45 字數 2350 閱讀 7085

題目模型

問題分析

錯誤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

*/

正確做法

我們只考慮交換的兩數乙個在答案區間,乙個不在的情況。

假設答案區間為 \([l,r]\) ,區間和為 \(sum_r-sum_\) ,假設我們把區間外的數 \(a_i\) 和區間內的數 \(a_j\) 進行交換,為了方便,令 \(i>j\) ,對於 \(i的情況,我們反過來處理一遍就行。則有:

對於減號的後面部分我們可以預處理出來,我們可以\(o(n^2)\)的把這個問題處理出來。

code

#include typedef long long ll;

const int maxn=50005;

const ll inf=1ll<<60;

ll n,ans;

ll a[maxn],sum[maxn],min[maxn];

void read()

void solve ()

ll mn=0;//記錄最小字首

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

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

}}int main()

分析上面的做法,實際上我們在掃瞄區間外交換元素 \(a_i\) 時,\(minj=min(a_j+min(sum_,sum_,...,sum_1,sum_0))\) 顯然很容易維護,所以我們不用從後往前掃瞄\(a_j\)了,對於從\(j+1\sim i-1\)之間的最大最大字首我們在掃瞄 \(a_i\) 過程中維護下就行,時間效率為:\(o(n)\) ,具體見下面註解。

code

#include typedef long long ll;

const int maxn=50005;

const ll inf=1ll<<60;

ll n,ans;

ll a[maxn],sum[maxn],min[maxn];

void read()

void solve ()

ll mn=0;//記錄最小字首

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

ll max=-inf;//維護最大的式子中除了a[i]部分

std::stack< std::pair> q;

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

else

break;

}q.push(std::make_pair(sum[i],minj));

max=std::max(max,sum[i]-minj);//當前的sum[i]-minj可能比以前記錄的大

}}int main()

數學比較差,先盜個鏈結,容我仔細琢磨透了仔細給大家講講:

hdu2830 可交換行的最大子矩陣

題意 求最大子矩陣,但是相鄰的列之間可以相互交換.思路 回想下固定的情況,記得那種情況是開倆個陣列 l i r i 記錄小於等於i的最左邊和最右邊在哪個位置,對於這個題目,可以交換,也就是說順序是可以自己隨意更改的,那麼我們直接sort一便,然後在找最大就行了,說下具體過程,便於理解 開始我們建立乙...

最大子段和

設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個...