vijos1369:难解的问题
描述
在你的帮助下,蔚蓝来到了埃及.在金字塔里,蔚蓝看到了一个问题,传说,能回答出这个问题的人就能受到埃及法老的祝福,可是蔚蓝日夜奋战,还是想不出来,你能帮帮他么?(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项的最长上升子序列的长度.
样例输入:
5 3
1 2 3 2 1
样例输出:
3
思路:将第k项左边大于等于第k项的去掉,左边小于等于第k项的去掉。
#include <iostream> #include <algorithm> using namespace std; const int MAXN=300005; const int INF=0x7fffffff; int h[MAXN],n,k; int a[MAXN],top; int dp[MAXN]; int lowbound(int l,int r,int val) { while(r-l>1) { int mid=(l+r)/2; if(dp[mid]>=val) { r=mid; } else { l=mid; } } return r; } int main() { cin>>n>>k; k--; for(int i=0;i<n;i++) { cin>>h[i]; dp[i]=INF; } for(int i=0;i<k;i++) { if(h[i]<h[k]) { a[top++]=h[i]; } } a[top++]=h[k]; for(int j=k+1;j<n;j++) { if(h[j]>h[k]) { a[top++]=h[j]; } } for(int i=0;i<top;i++) { int p=lowbound(-1,top,a[i]); dp[p]=a[i]; } int res=lowbound(-1,top,INF); cout<<res<<endl; return 0; }