题意:
给定一个序列A,删除任意个数的数,使得生成的新序列B={a,b,c,d….}与序列C={1,2,3,4…..}一一对应的数的个数最多,求最多能对应多少个数。
解析:
不妨列一下朴素的DP方程
f[i]=max(f[j]+1)(j<i且a[j]<a[i]且a[i]−a[j]<=i−j)
复杂度O(n^2),显然不可过,所以需要进一步优化。
观察三个限定条件。
1、j<i
2、a[j]<a[i]
3、a[i]−a[j]<=i−j即j−a[j]<=i−a[i]
容易发现已知 2,3 可以推出 1 。
而
而
所以我们不妨把 3 看做这
所以我们只需要按照
需要注意的是,如果
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100100
#define M 1000100
using namespace std;
struct node
{
int x,y;
friend bool operator < (node a,node b)
{
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
}b[N];
int d[M],a[N];
int n,ma,tot;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(i-a[i]<0)continue;
b[++tot].x=i-a[i],b[tot].y=a[i];
}
sort(b+1,b+tot+1);
memset(d,0x3f,sizeof(d));
for(int i=1;i<=tot;i++)
{
int l=1,r=ma,ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(b[i].y>d[mid])ans=mid,l=mid+1;
else r=mid-1;
}
ma=max(ma,ans+1);
d[ans+1]=min(d[ans+1],b[i].y);
}
printf("%d\n",ma);
}