Description
Mary在她的生日礼物中有一些积木。那些积木都是相同大小的立方体。每个积木上面都有一个数。Mary用他的
所有积木垒了一个高塔。妈妈告诉Mary游戏的目的是建一个塔,使得最多的积木在正确的位置。一个上面写有数i
的积木的正确位置是这个塔从下往上数第i个位置。Mary决定从现有的高塔中移走一些,使得有最多的积木在正确
的位置。请你告诉Mary她应该移走哪些积木。
1<=n<=100000,1<=ai<=1000000
Solution
题意不会复述,干脆直接贴上来
容易发现一个a[i]能接在a[j]后面需要满足
j<i
j
<
i
且
aj<ai
a
j
<
a
i
且
ai−aj≤i−j
a
i
−
a
j
≤
i
−
j
把第三个柿子划一下得到
i−ai≥j−aj
i
−
a
i
≥
j
−
a
j
,我们把序列按照柿子③排序,按照柿子②做最长不下降子序列,不难发现这样得出的答案一定是满足柿子①的
这就做完了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
const int L=1000005;
const int N=100005;
struct data {int x,y;} d[N];
int f[N+5],s[L+5];
bool cmp(data a,data b) {
return a.x<b.x||a.x==b.x&&a.y<b.y;
}
int main(void) {
int n; scanf("%d",&n);
rep(i,1,n) {
int x; scanf("%d",&x);
d[i].x=i-x;
d[i].y=x;
}
std:: sort(d+1,d+n+1,cmp);
fill(s,63); s[0]=0;
int ans=0;
rep(i,1,n) {
if (d[i].x<0) continue;
f[i]=1;
int l=1,r=ans;
while (l<=r) {
int mid=(l+r)>>1;
if (s[mid]>=d[i].y) r=mid-1;
else l=mid+1;
}
f[i]=l;
if (f[i]>ans) ans=f[i];
s[f[i]]=std:: min(s[f[i]],d[i].y);
}
// rep(i,0,ans) printf("%d\n", s[i]);
printf("%d\n", ans);
return 0;
}