nssl1488 上公升子串行 貪心,dp

2021-10-09 06:44:44 字數 1779 閱讀 6199

長度為n

nn的序列,分割成兩個上公升子串行要求長度差最小

我們對於i

ai≥a

ji

iai​≥

aj​的點之間連邊,然後可以對於乙個聯通塊進行二分圖染色,我們可以發現,如果我們先固定乙個點的顏色,那麼這個聯通塊的二分圖染色方案數為1或0。

之後兩個聯通塊互不影響,所以我們可以用dpdp

dp來計算方案。

考慮繼續優化,我們可以發現如果i

ii到j

jj之間有連邊,那麼對於任意乙個i

<

k

i<

kii和k

kk和j

jj必定聯通,那麼我們可以推得乙個聯通塊必定是乙個區間,而乙個區間的分界點滿足該點前面的所有數都比後面的所有數要小。

因為劃分方案數為2cn

t2^

2cnt

(cnt為聯通塊數量。所以聯通塊數量不超過log

(1e18

)log(1e18)

log(1e

18),可以通過本題

#include

#include

#include

#include

using

namespace std;

const

int n=

1e5+

10,k=

300;

int t,n,a[n]

,maxs[n]

,mins[n]

;int cnt,b[k]

,e[k]

,z[k]

;bool f[2]

[n];

stack<

int> q1,q2;

intmain()

mins[n+1]

=2147483647/3

;cnt=0;

for(

int i=n;i>=

1;i--

) mins[i]

=min

(mins[i+1]

,a[i]);

for(

int i=

1;i<=n;i++)if

(maxs[i]

<=mins[i+1]

||i==n)

b[++cnt]

=e[cnt-1]

+1,e[cnt]

=i;bool flag=0;

for(

int i=

1;i<=cnt;i++)}

if(flag)

break

; z[i]

=q1.

size()

-q2.

size()

;}if(flag)

memset

(f,0

,sizeof

(f))

; f[0]

[0]=

1;for(

int i=

1;i<=cnt;i++

)for

(int j=

0;j<=n;j++

) f[i&1]

[j]=f[

~i&1][

abs(j-z[i])]

|f[~i&1]

[abs

(j+z[i])]

;for

(int j=

0;j<=n;j++)if

(f[cnt&1]

[j])

}}

揹包 nssl 1488 上公升子串行

給乙個長度為 n 的陣列 a 試將其劃分為兩個嚴格上公升子串行,並使其長度差最小。當 max 1,i 時顯然兩個區間互不影響,把 i 視為分界點 若相鄰的兩個分界點 i,j 所組成的區間 i sim j 如果合法只有一種劃分方法 所以把合法區間貢獻扔入揹包裡搞一搞就可以了 include inclu...

上公升子串行

題目描述 乙個只包含非負整數的序列bi,當b1 b2 bs的時候,我們稱這個序列是上公升的。對於給定的乙個序列,我們可以得到一些上公升的子串行,這裡1 i1 i2 ik n。例如 對於序列,有它的一些上公升子串行,如,等等。這些子串行中序列和最大的是子串行,它的所有元素的和為18。對於給定的乙個序列...

上公升子串行

time limit 1000ms memory limit 65536k 乙個只包含非負整數的序列bi,當b1 b2 bs的時候,我們稱這個序列是上公升的。對於給定的乙個序列,我們可以得到一些上公升的子串行,這裡1 i1 i2 ik n。例如 對於序列,有它的一些上公升子串行,如,等等。這些子串行...