51nod 最大M子段和系列

2022-04-30 07:12:09 字數 3922 閱讀 6264

1052 最大m子段和

n個整數組成的序列a[1],a[2],a[3],…,a[n],將這n個數劃分為互不相交的m個子段,並且這m個子段的和是最大的。如果m >= n個數中正數的個數,那麼輸出所有正數的和。

例如:-2 11 -4 13 -5 6 -2,分為2段,11 -4 13一段,6一段,和為26。

input

第1行:2個數n和m,中間用空格分隔。n為整數的個數,m為劃分為多少段。(2 <= n , m <= 5000)

第2 - n+1行:n個整數 (-10^9 <= a[i] <= 10^9)

output

輸出這個最大和
input示例

7 2

-211

-413-56

-2

output示例

26

———————————————————————————————————

1254 最大子段和 v2

n個整數組成的序列a[1],a[2],a[3],…,a[n],你可以對陣列中的一對元素進行交換,並且交換後求a[1]至a[n]的最大子段和,所能得到的結果是所有交換中最大的。當所給的整數均為負數時和為0。

例如:將 -4 和 4 交換,,最大子段和為11 + 4 + 13 = 28。

input

第1行:整數序列的長度n(2 <= n <= 50000)

第2 - n + 1行:n個整數(-10^9 <= a[i] <= 10^9)

output

輸出交換一次後的最大子段和。
input示例

7

-211

-413

-5-2

4

output示例

28

——————————————————————————

因為這兩道題是一種寫法所以我就寫在一起

就把連續的一段正負的合在一起得到一段正負相間的序列

然後記錄一共有多少個正的記為tot 題目要保留的段數記為 k

那麼我們就需要消掉tot-k份 消掉的方法有放棄某一段正的或者是用一段負的把兩段正的合併

這樣我們維護乙個堆 權值是需要付出的代價 這樣慢慢合併就能解決問題了

記得記錄每一段的相鄰段就好辣 當然記得特判邊界 我的處理方法是加一段權值為負無窮的段就好辣

#include#include

#include

#include

#define ll long long

using

namespace

std;

const

int m=1e6+1e5+7

;const ll inf=1e15;

ll read()

while(c>='

0'&&c<='9')

return ans*f;

}int

n,k,f[m],lx[m],rx[m];

ll cnt,sum[m],v,ans;

bool pd(ll x,ll y)

ll pabs(ll x)

struct

node

};priority_queue

q;int

main()

if(pd(sum[cnt],-inf)) sum[cnt]+=-inf;

else sum[++cnt]=-inf;

int tot=0; for(int i=1;i<=cnt;i++)if(sum[i]>=0) ans+=sum[i],tot++;

if(tot<=k) return printf("

%lld\n

",ans),0

;

int now=tot-k;

for(int i=1;i<=cnt;i++) q.push((node)),lx[i]=i-1,rx[i]=i+1

; lx[

1]=cnt; rx[cnt]=1

;

while

(now));

lx[cnt]=lx[l]; rx[cnt]=rx[r];

rx[lx[l]]=cnt; lx[rx[r]]=cnt;

}printf(

"%lld\n

",ans);

return0;

}

view code

1115 最大m子段和 v3

環形最大m子段和,n個整數組成的序列排成乙個環,a[1],a[2],a[3],…,a[n](a[n-1], a[n], a[1]也可以算作1段),將這n個數劃分為互不相交的m個子段,並且這m個子段的和是最大的。如果m >= n個數中正數的個數,那麼輸出所有正數的和。

例如:-2 11 -4 13 -5 6 -1,分為2段,6 -1 -2 11一段,13一段,和為27。

input

第1行:2個數n和m,中間用空格分隔。n為整數的個數,m為劃分為多少段。(2 <= n , m <= 100000)

第2 - n+1行:n個整數 (-10^9 <= a[i] <= 10^9)

output

輸出這個最大和
input示例

7 2

-211

-413-56

-2

output示例

26

————————————————————————

這道題不需要特判邊界反而更容易qaq

#include#include

#include

#include

#include

#include

#define ll long long

using

namespace

std;

const

int m=1500007

;ll read()

while(c>='

0'&&c<='9')

return ans*f;

}ll lx[m],rx[m],w[m];

ll n,k,tot;

ll cnt=1

;ll sum[m],ans;

bool

f[m];

struct

node

};priority_queue

q;ll pd(ll x)

bool okay(ll a,ll b)

intmain()

if(okay(sum[1],sum[cnt])) sum[1]=sum[cnt]+sum[1],cnt--;

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

if(sum[i]>0) ans+=sum[i],tot++;

if(tot<=k)

ll now=tot-k;

q.push((node));

lx[1]=cnt; rx[1]=2; w[1]=pd(sum[1

]); q.push((node));

lx[cnt]=cnt-1; rx[cnt]=1; w[cnt]=pd(sum[cnt]);

for(int i=2;i)

q.push((node)),lx[i]=i-1,rx[i]=i+1,w[i]=pd(sum[i]);

while

(now));

lx[cnt]=lx[l]; rx[cnt]=rx[r];

rx[lx[l]]=cnt; lx[rx[r]]=cnt;

}printf(

"%lld\n

",ans);

return0;

}

view code

51nod 最大子段和

給出乙個整數陣列a 正負數都有 如何找出乙個連續子陣列 可以乙個都不取,那麼結果為0 使得其中的和最大?例如 2,11,4,13,5,2,和最大的子段為 11,4,13。和為20。輸入 第1行 整數序列的長度n 2 n 50000 第2 n 1行 n個整數 10 9 a i 10 9 輸出 輸出最大...

51nod 最大子段和

題面 以乙個長為n的數列,求連續子段的最大值。思路1直接列舉o n 3 tle穩穩的 include using namespace std int n,a 50050 ans int main ans max ans,t 更新最值 cout n return 0 字首和優化的列舉法,o n 2 還...

51Nod 1052 最大M子段和

n個整數組成的序列a 1 a 2 a 3 a n 將這n個數劃分為互不相交的m個子段,並且這m個子段的和是最大的。如果m n個數中正數的個數,那麼輸出所有正數的和。例如 2 11 4 13 5 6 2,分為2段,11 4 13一段,6一段,和為26。刷刷水有益身心健康。不過我還是沒有一眼看出來。考慮...