題目模型
問題分析
錯誤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個...