luogu P2215 [HAOI2007]上升序列
阿新 • • 發佈:2017-10-04
最小 esp family 字典 hide play 描述 cout bool
P2215 [HAOI2007]上升序列
題目描述
對於一個給定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},滿足(x1<x2<…<xm) 且(ax1<ax2<…<axm)。那麽就稱P為S的一個上升序列。如果有多個P滿足條件,那麽我們想求字典序最小的那個。
任務 給出S序列,給出若幹詢問。對於第i個詢問,求出長度為Li的上升序列,如有多個,求出字典序最小的那個(即首先x1最小,如果不唯一,再看x2最小……),如果不存在長度為Li的上升序列,則打印Impossible.
輸入輸出格式
輸入格式:
第一行一個N,表示序列一共有N個元素
第二行N個數,為a1,a2,…,an
第三行一個M,表示詢問次數。下面接M行每行一個數L,表示要詢問長度為L的上升序列。
輸出格式:
對於每個詢問,如果對應的序列存在,則輸出,否則打印Impossible.
輸入輸出樣例
輸入樣例#1:6 3 4 1 2 3 6 3 6 4 5輸出樣例#1:
Impossible 1 2 3 6 Impossible
說明
數據範圍
N<=10000
M<=1000
n^2的lis能過。數據滿水的。反向找這個點最多以他為開頭能擴展幾個數.O(n*m+n*n)直接過
#include<iostream> #include上升序列<cstdio> #include<cstdlib> #include<algorithm> using namespace std; const int INT=1e9+7; const int maxn=100000+999; int read(){ int an=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();}return an*f; } int a[maxn],f[maxn],n,m; int main(){ n=read(); for(int i=1;i<=n;i++)a[i]=read(); f[n]=1; for(int i=n;i>0;i--){ for(int j=n;j>i;j--) if(a[i]<a[j]) f[i]=max(f[j]+1,f[i]); } m=read(); while(m){ m--; int k=read(),last=-INT; for(int i=1;i<=n;i++){ if( f[i]>=k&&k&&last<a[i] ){ cout<<a[i]<<" "; k--; last=a[i]; } } if(k)cout<<"Impossible"<<endl; else cout<<endl; } }
by:s_a_b_e_r
水題qwq
開始以為挺難的,然而s一看這題,“這不就LIS嗎”
反著求一遍LIS,求出以i開頭的LIS長度
然後對於每個詢問,從頭掃一遍,如果有長度≥當前詢問的直接輸出就好了(貪心)
#include<iostream> #include<cstdio> using namespace std; const int N=10009,M=1009; int a[N],n,m,f[N]; int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=n;i>=1;--i) { f[i]=1; for(int j=n;j>=i;--j) if(a[i]<a[j])f[i]=max(f[i],f[j]+1); } scanf("%d",&m); while(m--) { int l,k=0; scanf("%d",&l); bool flag=1; for(int i=1;i<=n&&l;++i) if(f[i]>=l&&a[i]>k) { flag=0; printf("%d ",a[i]); k=a[i]; --l; } if(flag)printf("Impossible"); cout<<endl; } return 0; }上升序列
by:wypx
luogu P2215 [HAOI2007]上升序列