题意中文。不过注意是相隔距离相差>d的LIS不是两两大小差>d。。我就这点看错了
这题看了别人的博客才看懂,不过我觉得他们都没有写清楚,花时间模拟了下才弄懂。
有一个单调队列跟普通的LIS是一样的,不过这个单调队列对于当前加入的a[i]来说它里面保存的值都是 [ 0 , i-d ) 的最优值,所以当前通过二分加进来的值与队列里任何一个值的距离都是>d的,加进了i就去在单调队列里更新i-d这个位置加进来的值,这样就保证了我前面说的每次加进来都是 满足距离>d的条件的。这样说就应该说清楚了。
AC代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<ctime>
#include<string.h>
#include<string>
#include<bitset>
using namespace std;
#define ll __int64
#define eps 1e-8
#define NMAX 100000+10
template<class T>
inline void scan_d(T &ret)
{
char c;
int flag = 0;
ret=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c == '-')
{
flag = 1;
c = getchar();
}
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
if(flag) ret = -ret;
}
int a[NMAX],g[NMAX],d[NMAX];
int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o4.txt","w",stdout);
#endif // GLQ
int n,p,i,j;
while(~scanf("%d%d",&n,&p))
{
for(i = 1; i <= n; i++)
scan_d(a[i]);
for(i = 1; i <= n; i++) g[i] = NMAX;
memset(d,0,sizeof(d));
for(i = 1; i <= n; i++)
{
d[i] = lower_bound(g+1,g+1+n,a[i])-g;
if(i - p > 0) g[d[i-p]] = min(a[i-p],g[d[i-p]]);
}
int ans = 0;
for(i = 1; i <= n; i++) ans = max(ans,d[i]);
printf("%d\n",ans);
}
return 0;
}