BZOJ 1109 [POI2007]堆积木Klo

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=1109

思路

神奇的dp转化:

fi f i 表示第 i i 块正确的时候,第i块前面有多少块摆放正确。

朴素dp方程:

fi=fj+1[i>j(1),ai>aj(2),aiiajj(3)] f i = f j + 1 [ i > j ( 1 ) , a i > a j ( 2 ) , a i − i ≤ a j − j ( 3 ) ]

很容易看出,若 (2)(3) ( 2 ) ( 3 ) 两条件满足, (1) ( 1 ) 条件一定满足。

若按照 ai a i 排序,就变成了对 aii a i − i 求最长不上升子序列。

好神奇啊。

代码

#include <cstdio>
#include <algorithm>

const int maxn=100000;
const int inf=0x3f3f3f3f;

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

struct pps
{
  int x,y;

  bool operator <(const pps &other) const
  {
    if(x==other.x)
      {
        return y>other.y;
      }
    return x<other.x;
  }
};

pps p[maxn+10];
int n,len,f[maxn+10],tot;

int main()
{
  n=read();
  for(register int i=1; i<=n; ++i)
    {
      int a=read();
      if(a<=i)
        {
          p[++tot].x=a;
          p[tot].y=i-a;
        }
    }
  if(!tot)
    {
      puts("0");
      return 0;
    }
  std::sort(p+1,p+tot+1);
  f[1]=p[1].y;
  len=1;
  for(register int i=2; i<=tot; ++i)
    {
      int pos=std::upper_bound(f+1,f+len+1,p[i].y)-f;
      f[pos]=p[i].y;
      if(pos>len)
        {
          len=pos;
        }
    }
  printf("%d\n",len);
  return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值