LuoGu 1108 低價購買 LIS方案數
阿新 • • 發佈:2018-10-17
std ans 其中 有一個 怎麽 pri clu 轉移 影響
一句話題意:兩個序列的LIS的長度和方案數
首先這裏n方的應該是要比nlog的好的,因為還涉及到一個求方案
主要考慮下第二問, 不同的方案數應該怎麽求
實際上 對於一個長為len的子序列,
它的方案數即為所有長為len-1的,且可以轉移到它的子序列 (都是滿足題意的)的方案數之和
這樣就比較好辦了,直接在原本的求LIS的轉移裏搞搞就行了。
那麽答案就是所有長度為LIS的方案數之和了。
但是還有一個問題,這樣的話根本沒考慮方案是否重復。
那麽怎麽樣把相同的去掉呢??
我們把長度相等,當前對應位上的數也相等的,就先暫定為相等,刪掉其中一個。
因為如果他們之前的也相同, 那麽我們是可以直接全轉移到當前的,刪掉之前的。
如果之前的不相等, 那麽之後它們的後面接上一個不同的數時,再作為兩個判斷就行了,互不影響。
貼下代碼
#include<bits/stdc++.h> using namespace std; inline int gi() { int x=0,w=0;char ch=0; while(!(ch>=‘0‘&&ch<=‘9‘)) { if(ch==‘-‘) w=1; ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘) x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return w?-x:x; } int n,post[5001],tot[5001],maxn,times[5001]; long long ans; int main() { n=gi(); for(int i=1;i<=n;i++) { post[i]=gi(); tot[i]=1; } for(int i=1;i<=n;i++) { for(int j=1;j<i;j++) if(post[i]<post[j]) tot[i]=max(tot[i],tot[j]+1); if(tot[i]>maxn) maxn=tot[i]; for(int j=1;j<i;j++) { if(tot[i]==tot[j]&&post[i]==post[j]) times[j]=0; else if(tot[i]==tot[j]+1&&post[i]<post[j]) times[i]+=times[j]; } if(!times[i]) times[i]=1; } for(int i=1;i<=n;i++) if(tot[i]==maxn) ans+=times[i]; printf("%d %d",maxn,ans); return 0; }
LuoGu 1108 低價購買 LIS方案數