4.17记录 LIS其二

4.17记录 LIS其二

输出最终结果的LIS。
思路相比传统的LIS来讲,一是原来的队列二分不那么好用了(队列模拟最终得出来的那个所谓LIS实际并不是真实的情况),二是需要加一点东西来存这个队列,也就是链表。
建议熟读并背诵。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int head[100001],a[100001];
void find(int x){
	if(~head[x]) find(head[x]);
	printf("%d ",a[x]);
}
int main(){
	int n = 0,i,j,rear,telipu = -1,dp[100001];
	memset(head,-1,sizeof(head));
	while(scanf("%d",&a[++n]) != EOF);
	--n;
	for(i = 1;i <= n;i++) dp[i] = 1;
	for(i = 2;i <= n;i++){
		for(j = 1;j < i;j++){
			if(a[j] < a[i] && dp[j] + 1 > dp[i]){
				dp[i] = dp[j] + 1;
				head[i] = j;
				if(telipu < dp[i]){//维护一个最大值
					telipu = dp[i];
					rear = i;
				}
			}
			//dp[i] = max(dp[i],dp[j]);
		}
	}
	printf("max=%d\n",telipu);
	find(rear);
	return 0;
}

除此之外,还有一个导弹拦截问题。这题可以队列模拟了,不过二分比较讲究。
这题直接一分为二(源代码中我也加上了分隔),前半段是最长不上升子序列,find找的是第一个不大于它的数;后半段是最长上升子序列,find找的是第一个不小于它的数。所以这两次替换l = mid + 1的条件是不一样的,一次是大于等于,一次是小于。这和别的二分处理方式是一样的,看最后两个数的取法决定到底带不带等。
总之感觉这题考的不是贪心也不是DP而是二分…

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int Q[100001],a[100001],rear;
int find(int x){
	int l = 1,r = rear,mid;
	while(l < r){
		mid = (l + r) >> 1;
		if(Q[mid] < x) r = mid;
		else l = mid + 1;
	}
	return l;
}
int anfind(int x){
	int l = 1,r = rear,mid;
	while(l < r){
		mid = (l + r) >> 1;
		if(Q[mid] < x) l = mid + 1;
		else r = mid;
	}
	return l;
}
int main(){
	int i,j,k,n = 0;
	Q[0] = 2e9;
	while(scanf("%d",&a[++n]) != EOF);
	--n;
	for(i = 1;i <= n;i++){
		if(Q[rear] >= a[i]) Q[++rear] = a[i];
		else{
			k = find(a[i]);
			Q[k] = a[i];
		}
	}
	printf("%d\n",rear);
//--------------------------------------------------
	memset(Q,0,sizeof(Q));
	rear = 0;
	for(i = 1;i <= n;i++){
		if(Q[rear] < a[i]) Q[++rear] = a[i];
		else{
			k = anfind(a[i]);
			Q[k] = a[i];
		}
	}
	printf("%d\n",rear);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值