P2215 [HAOI2007]上升序列(LIS)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2215 [HAOI2007]上升序列(LIS)相关的知识,希望对你有一定的参考价值。

P2215 [HAOI2007]上升序列(LIS)

本题关键在在于求出以 i i i开头的 L I S LIS LIS的长度。

与普通的 L I S LIS LIS不同,普通的 L I S LIS LIS是求以 a i a_i ai结尾的最大长度。

因此考虑倒着贪心,优先用较大的数,另外本题可以类似 O ( n l o g n ) O(nlogn) O(nlogn)的优化,用一个数组维护对应长度的最大 a i a_i ai, 然后倒着递推即可.

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

// Problem: P2215 [HAOI2007]上升序列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2215
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-07-02 23:07:23
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e4+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int a[N],b[N],f[N],n,m,tot;
int fun(int x){
	int ans=0;
	int l=1,r=tot;
	while(l<=r){
		int mid=l+r>>1;
		if(b[mid]>x) ans=mid,l=mid+1;
		else r=mid-1;
	}
	return ans;
}
void solve(){
	for(int i=n;i;i--){
		f[i]=fun(a[i])+1;
		tot=max(tot,f[i]);
		if(b[f[i]]<a[i]) b[f[i]]=a[i];
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	solve();
	scanf("%d",&m);while(m--){
		int x;scanf("%d",&x);
		if(x>tot) puts("Impossible");
		else {
			int la=0;
			for(int i=1;i<=n&&x;i++){
				if(f[i]>=x&&a[i]>la){
					printf("%d ",a[i]);
					x--,la=a[i];
				}
			}
			printf("\\n");
		}
	}
	return 0;
}

以上是关于P2215 [HAOI2007]上升序列(LIS)的主要内容,如果未能解决你的问题,请参考以下文章

P2215 [HAOI2007]上升序列

P2215 [HAOI2007]上升序列 DP

bzoj 1046 : [HAOI2007]上升序列 dp

BZOJ1046 : [HAOI2007]上升序列

bzoj1046[HAOI2007]上升序列

1046: [HAOI2007]上升序列(dp)