BZOJ3591 最長上公升子串行

2021-08-16 15:28:15 字數 1499 閱讀 6357

考慮我們做最長上公升子的過程,維護乙個單調棧,每次加入乙個元素,替換掉最前面乙個比他大的數

我們可以dp這個加入元素的過程,用乙個3進製的狀態表示每個數在不在佇列裡且在不在棧裡,可以用o(

n22n

) o(n

22n)

預處理對於棧中的每個狀態,加入乙個新的數之後的狀態

然後做乙個o(

n3n)

o (n

3n

)的dp,注意要按當前序列內的元素數量從小到大dp

code:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

#define lowbit(x) (x)&(-(x))

using

namespace

std;

const

int maxn = 16;

const

int mask = 14348907;

int pw[maxn];

int n,m;

int a[maxn],pre[maxn];

int nex[maxn],t[maxn],tp;

int to[1

<1

<1

<1

queue

q;int ans;

int main()

int al=1

<0]=-1; to3[0]=-1;

for(int i=0;ifor(int j=1;j<=n;j++) t[j]=i>>j-1&1;

int ev=0;

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

sum[i]=sum[i^lowbit(i)]+1;

to3[i]=to3[i^lowbit(i)]+pw[to[lowbit(i)]];

}f[0]=1; q.push(0);

while(!q.empty())

bool ok=true;

for(int j=1;j<=n;j++) if(!t[j])

}//printf("%d ",temp);

//for(int i=1;i<=n;i++) printf("%d ",t[i]); putchar('\n');

if(ok) ans+=temp;

}printf("%d\n",ans);

return

0;}

BZOJ 3591 最長上公升子串行

哎我還是太菜了,這麼短的 斷斷續續 調了好久。看資料範圍 大概就是狀壓dp 題目名字是 最長上公升子串行 可以猜測是拿跑li s 的單調棧搞搞。那麼可以設計乙個狀態f a b 表示已選集合 a 其中 b是當前單調棧裡的元素,顯然棧裡的元素公升序排列,不用額外加一維狀態表示棧中元素的排列。顯然這可以優...

BZOJ 3591 最長上公升子串行

題目鏈結 題意 給定 k kk 個數,求所有長度為 n nn 且最長上公升子串行的排列為給定的 k kk 個數的方案數。n 15 n 15 n 1 5首先想到可以用狀壓解決排列的順序問題,而僅通過 0,1 0,10,1 無法表達出最長上公升子串行的長度,而再開一維進行表示也無法進行有效轉移。那麼考慮...

BZOJ3591 最長上公升子串行 狀壓DP

description 給出1 n的乙個排列的乙個最長上公升子串行,求原排列可能的種類數。sample input53 1 3 4 sample output 11挺好的dp題。我們先考慮普通lis,我們維護乙個序列,每一次盡量去替換序列中的值。對於這個,可以用乙個三進製維護,0表示未進佇列,1表示...