https://www.luogu.org/problem/P2215
初看题目,不就是个最长上升子序列吗?
但我们知道nlogn的最长上升子序列中定义状态f[i]表示以i结尾的...
这个题要求以i开头的
所以倒着做最长下降子序列就好了,f只记录长度(解题关键,逆向思考)
但我发现我一直wa
wa的代码:
#include<bits/stdc++.h>
#define ll long long
#define il inline
#define ri register int
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=10005;
int n,m,maxx;
int dp[maxn],C[maxn],a[maxn],t[maxn],xx[maxn];
il void add(int x,int p){while(x)C[x]=max(C[x],p),x-=lowbit(x);return;}
il int query(int x){int res=0;while(x<=n)res=max(res,C[x]),x+=lowbit(x);return res;}
int main(){
scanf("%d",&n);
for(ri i=1;i<=n;i++)scanf("%d",&a[i]),t[i]=xx[i]=a[i];
sort(t+1,t+1+n);int sz=unique(t+1,t+1+n)-t-1;
for(ri i=1;i<=n;i++)a[i]=lower_bound(t+1,t+1+n,a[i])-t;
for(ri i=n;i>=1;i--){
dp[i]=query(a[i]+1)+1;
add(a[i],dp[i]);
maxx=max(maxx,dp[i]);
}
scanf("%d",&m);
while(m--){int x;scanf("%d",&x);
if(x>maxx){printf("Impossible\n");continue;}
for(ri i=1;i<=n;i++){
if(!x){cout<<endl;break;}
if(dp[i]==x)printf("%d ",xx[i]),x--;
}
}
return 0;
}
为什么呢?因为我太弱了。
输出的时候根本无法满足它是最长上升的,我只转移了长度
AC CODE
#include<bits/stdc++.h>
#define ll long long
#define il inline
#define ri register int
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=10005;
int n,m,maxx;
int dp[maxn],C[maxn],a[maxn],t[maxn],xx[maxn];
il void add(int x,int p){while(x)C[x]=max(C[x],p),x-=lowbit(x);return;}
il int query(int x){int res=0;while(x<=n)res=max(res,C[x]),x+=lowbit(x);return res;}
int main(){
scanf("%d",&n);
for(ri i=1;i<=n;i++)scanf("%d",&a[i]),t[i]=xx[i]=a[i];
sort(t+1,t+1+n);int sz=unique(t+1,t+1+n)-t-1;
for(ri i=1;i<=n;i++)a[i]=lower_bound(t+1,t+1+n,a[i])-t;
for(ri i=n;i>=1;i--){
dp[i]=query(a[i]+1)+1;
add(a[i],dp[i]);
maxx=max(maxx,dp[i]);
}
scanf("%d",&m);
while(m--){int x;scanf("%d",&x);
if(x>maxx){printf("Impossible\n");continue;}
int last=0;
for(ri i=1;i<=n;i++)
if(dp[i]>=x&&xx[i]>last){
printf("%d ",xx[i]),x--,last=xx[i];
if(!x)break;
} puts("");
}
return 0;
}