题目描述:
QAQ…
题目分析:
设 F[i] 为 以 i 为开头最大的上升子序列长度 可以
NlogN
N
l
o
g
N
求,不再概述了
然后对于每个查询,我们
O(n)
O
(
n
)
去扫 当F[i]>=k 并且大于上一个数的时候,这个数即为我们要求的数列项之一,由于我们是从前往后扫的,所以字典序有保证,不要忘了把长度减小1
线段树完全可以用树状数组代替,然后我闲得慌...
题目链接:
Ac 代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
const int maxm=11000;
int hash[maxm],a[maxm],dp[maxm];
int maxi[maxm<<2];
int n,m,maxlen;
void insert(int o,int l,int r,int ind,int val)
{
if(l>=r) return (void)(maxi[o]=val);
int mid=(l+r)>>1;
ind<=mid?insert((o<<1),l,mid,ind,val):insert((o<<1)|1,mid+1,r,ind,val);
maxi[o]=std::max(maxi[(o<<1)],maxi[(o<<1)|1]);
}
int ask(int o,int l,int r,int ql,int qr)
{
if(r<ql||l>qr) return 0;
if(ql<=l&&r<=qr) return maxi[o];
int mid=(l+r)>>1;
int ans=0;
if(ql<=mid) ans=std::max(ans,ask((o<<1),l,mid,ql,qr));
if(qr>mid) ans=std::max(ans,ask((o<<1)|1,mid+1,r,ql,qr));
return ans;
}
inline void slove(int k)
{
int maxx=0;
for(int i=1;i<=n;i++)
if(dp[i]>=k&&a[i]>maxx)
{
printf("%d ",hash[a[i]]);
maxx=a[i];
k--;
if(k==0) {puts("");return;}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),hash[i]=a[i];
std::sort(hash+1,hash+n+1);
int t=std::unique(hash+1,hash+n+1)-hash-1;
for(int i=1;i<=n;i++) a[i]=std::lower_bound(hash+1,hash+t+1,a[i])-hash;
for(int i=n;i>=1;i--) dp[i]=ask(1,1,t,a[i]+1,t)+1,insert(1,1,t,a[i],dp[i]),maxlen=std::max(maxlen,dp[i]);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int k;
scanf("%d",&k);
if(k>maxlen) puts("Impossible");
else slove(k);
}
return 0;
}