Description
间桐慎二是间桐家著名的废柴,有一天,他在学校随机了一组随机数列, 准
备使用他那强大的人工智能求出其最长上升子序列,但是天有不测风云,人有旦
夕祸福,柳洞一成路过时把间桐慎二的水杯打翻了……
现在给你一个长度为 n 的整数序列,其中有一些数已经模糊不清了,现在请
你任意确定这些整数的值,使得最长上升子序列最长(为何最长呢?因为间桐慎
二向来对自己的人品很有信心) 。
Input
第一行一个正整数 n。
接下来 n 行,第 i 行若为“K x” ,则表示第 i 个数可以辨认且这个数为 x;
若为“N” ,则表示第i 个数已经辨认不清了。
Output
第一行一个整数,表示最长的最长上升子序列长度。
Sample Input
4
K 1
N
K 2
K 3
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;
}