bzoj1109 [POI2007]堆积木Klo dp

123 篇文章 0 订阅

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 aiajij a i − a j ≤ i − j
把第三个柿子划一下得到 iaijaj 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值