考慮我們做最長上公升子的過程,維護乙個單調棧,每次加入乙個元素,替換掉最前面乙個比他大的數
我們可以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表示...