BZOJ 4282 慎二的随机数列 动态规划

本文介绍了一个关于最长上升子序列(LIS)的问题,探讨如何在包含不确定数值的序列中找到最长上升子序列的方法。通过调整不确定数值,可以最大化序列的上升特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

间桐慎二是间桐家著名的废柴,有一天,他在学校随机了一组随机数列, 准
备使用他那强大的人工智能求出其最长上升子序列,但是天有不测风云,人有旦
夕祸福,柳洞一成路过时把间桐慎二的水杯打翻了……
现在给你一个长度为 n 的整数序列,其中有一些数已经模糊不清了,现在请
你任意确定这些整数的值,使得最长上升子序列最长(为何最长呢?因为间桐慎
二向来对自己的人品很有信心) 。

Input

第一行一个正整数 n。
接下来 n 行,第 i 行若为“K x” ,则表示第 i 个数可以辨认且这个数为 x;
若为“N” ,则表示第i 个数已经辨认不清了。

Output

第一行一个整数,表示最长的最长上升子序列长度。

Sample Input

4
K 1
N
K 2
K 3

Sample Output

3

HINT

对于100%的数据,n ≤ 100000,|x| ≤ 10^9









orz yzh dalao~

N是不确定元素,
考虑N怎么去用,假如对于一个最长的上升序列,它不包含某一个N,
那么完全可以去掉某个位置上的数,然后用这个N去代替的;
所以可以看作所有'N'都用上了。

接着考虑:比如1,N,3,显然我们会令N=2;
比如1,N,N,4,显然会让序列变成1,2,3,4;
那如果是1,N,N,3呢?最长上升序列长度就只有3了。
推广一下这个小思路,假如是x,p个N,y,假设y>x
那么当y-x>p的时候,我们很容易想到序列变成了x,x+1,x+2,……y
那么如果y-x=w<=p呢?那么这个最长上升的序列长度就不是p+2了,而是w+1了;
可以看作,x<y-p和x>=y-p,只要把y减掉'N'的个数,就可以直接比较x和y了,
也就是……
对于第i个数,假设前面出现了p个N,那么第i个数减去p;
然后求出这个构造出的序列的LIS,再加上所有'N'的个数(‘N’全取)就是答案。
为什么是对的呢……就看上面说的一点内容吧……

大致总结证明一下:
如果新序列里能够继续满足上升的,那么中间所有的'N'即可取;
之前已经说过,最优解里肯定所有'N'都取了;
所以只要求新序列的最长上升子序列即可。

LIS二分总是要打错很烦躁……



#include<bits/stdc++.h>
using namespace std;
const int 
	N=100005;
int n,p,b[N],a[N];
void BS(int x){
	int l=1,r=p,mid;
	while (l<r){
		mid=(l+r)>>1;
		if (x>b[mid]) l=mid+1;
		 else r=mid;
	}
	b[l]=x;
}
int LIS(int maxn){
	if (!maxn) return 0;
	b[p=1]=a[1];
	for (int i=2;i<=maxn;i++)
		if (a[i]>b[p]) b[++p]=a[i];
			else BS(a[i]);
	return p;
}
int main(){
	scanf("%d",&n);
	int t=0,t1,m=0;
	char s[2];
	for (int i=1;i<=n;i++){
		scanf("%s",s);
		if (s[0]=='N') t++; else
		scanf("%d",&t1),a[++m]=t1-t;
	}
	printf("%d\n",LIS(m)+t);
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值