code vs 2188 最长上升子序列(线段树优化DP)

2188 最长上升子序列

 时间限制: 1 s
 空间限制: 32000 KB
 题目等级 : 钻石 Diamond
题解
 查看运行结果
题目描述 Description

LIS问题是最经典的动态规划基础问题之一。如果要求一个满足一定条件的最长上升子序列,你还能解决吗?

    给出一个长度为N整数序列,请求出它的包含第K个元素的最长上升子序列。

    例如:对于长度为6的序列<2,7,3,4,8,5>,它的最长上升子序列为<2,3,4,5>,但如果限制一定要包含第2个元素,那么满足此要求的最长上升子序列就只能是<2,7,8>了。

输入描述 Input Description

第一行为两个整数N,K,如上所述。

    接下来是N个整数,描述一个序列。

 

输出描述 Output Description

请输出两个整数,即包含第K个元素的最长上升子序列长度。

样例输入 Sample Input

8 6

65 158 170 299 300 155 207 389

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

80%的数据,满足0

    100%的数据,满足0


题解:线段树优化DP

把K之前小于K的值保留下来,K之后大于K的值保留下来,然后做最长上升子序列,就是这个题的答案,但是如果每次找当前点前面比这个点的值小的更新答案,时间复杂度n^2,所以我们可以把权值离散化,然后建立一颗权值线段树,来维护f[i]的值,每次更新的时候只需要求出这个点在权值线段树中之前点的最大值即可,0(n log n ) 

#include
#include
#include
#include
#define N 2000003
using namespace std;
int n,k,a[N],f[N],num[N],cnt,mark;
int b[N],q[N],tr[N*8];
int cmp(int x,int y)
{
	return num[x]=ll&&r<=rr)  return tr[now];
	int mid=(l+r)/2;
	int maxn=0;
	if (ll<=mid)  maxn=max(maxn,qjmax(now<<1,l,mid,ll,rr));
	if (rr>mid) maxn=max(maxn,qjmax(now<<1|1,mid+1,r,ll,rr));
	return maxn;
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("my.out","w",stdout);
	scanf("%d%d",&n,&k);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int i=1;i<=n;i++)
	 {
	 	if (a[i]i)  num[++cnt]=a[i]; 
	 	if (a[i]>a[k]&&k


你可能感兴趣的:(动态规划,线段树)