vijos 难解的问题

描述


在你的帮助下,蔚蓝来到了埃及.在金字塔里,蔚蓝看到了一个问题,传说,能回答出这个问题的人就能受到埃及法老的祝福,可是蔚蓝日夜奋战,还是想不出来,你能帮帮他么?(XXX: 胡扯,教主怎么可能想不出来= _ =||)(WS这人说的=。=)
问题是这样的: 
给定一个序列<a1,a2,\.\.\.,an>.求最长上升子序列(lis)p1<p2<\.\.\.<pw满足a[p1]<a[p2]<\.\.\.<a[pw]
例如65 158 170 299 300 155 207 389
LIS=<65,158,170,299,300,389>。
但是,现在还有一个附加条件:求出的最长上升子序列必须含有第K项。
比如,在上面的例子中,要求求出的最长上升子序列必须含有第6项,那么最长上升子序列就是:65 155 207 389。
格式


输入格式


第一行是用空格隔开的两个正整数N、K,含义同上所述.
第二行N个数,即给出的序列.
输出格式


仅有一个数,表示含有第K项的最长上升子序列的长度.
样例1


样例输入1


5 3
1 2 3 2 1
Copy
样例输出1


3
Copy
限制


各个测试点1s
提示


对于60%的数据,N<=10000;

对于100%的数据,1<=n<=300000 ,1<=k<=n,序列的每一个数为小于2^31-1 的非负整数.

题解:LIS二分

#include <bits/stdc++.h>
#include<iostream>
using namespace std;
const int MAXN=300005;

long long dp[MAXN];
long long a[MAXN];
int binary_search(int i, int len){
	int left,right,mid;
	left=1,right=len;
	while(left<right){
		mid = left+(right-left)/2;
		if(dp[mid] >= a[i]) right=mid ;
		else left=mid+1;
	}
	return left;
}

int main()
{
    int n,k;
    long long int temp;
    cin>>n>>k;
    for(int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    dp[1] = a[1];
    int len = 1;
    for(int i = 2; i <= k; ++i) {   //以a[k]结尾的最长上升子序列
        if(a[i]>dp[len])
            dp[++len] = a[i];
        else {
            int pos = binary_search(i,len);
            //int pos = lower_bound(dp+1, dp + len, a[i]) -dp;  或者用库函数
            dp[pos] = a[i];
            if(i==k)     //如果不能放在最后
                len = pos;
        }
    }
    int ans = 1;
    dp[1] = a[k];
    for(int i = k+1; i <= n; ++i) {
        if(a[i] > dp[ans])
            dp[++ans] = a[i];
        else {
            int pos = binary_search(i,ans);
            //int pos = lower_bound(dp+1, dp + ans, a[i]) - dp; 
            if(pos != 1)
                dp[pos] = a[i];
        }
    }
    printf("%d\n", ans + len - 1);
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值