BZOJ1109 : [POI2007]堆积木Klo

f[i]表示第i个在自己位置上的最大值

则f[i]=max(f[j])+1

其中

j<i

a[j]<a[i]

a[i]-a[j]<=i-j -> j-a[j]<=i-a[i]

i-a[i]>=0

j-a[j]>=0

发现后两项可以推出第一项,所以是一个LIS问题,排序后树状数组优化DP即可,时间复杂度$O(n\log n)$。

 

#include<cstdio>
#include<algorithm>
#define N 100010
int n,i,j,k,a[N],b[N],bit[N],t,f[N],ans;
struct E{int x,y;E(){}E(int _x,int _y){x=_x,y=_y;}}e[N];
inline bool cmp(E a,E b){return a.x<b.x;}
inline int lower(int x){
  int l=1,r=n,mid,t;
  while(l<=r)if(b[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
  return t;
}
inline void ins(int x,int y){for(;x<=n;x+=x&-x)if(bit[x]<y)bit[x]=y;}
inline void ask(int x){for(;x;x-=x&-x)if(t<bit[x])t=bit[x];}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int main(){
  for(read(n),i=1;i<=n;i++)read(j),e[i]=E(j,i-j),b[i]=i-j;
  std::sort(e+1,e+n+1,cmp),std::sort(b+1,b+n+1);
  for(i=1;i<=n;i=j){
    for(j=i;j<=n&&e[j].x==e[i].x;j++)if(e[j].y>=0){
      t=0,ask(e[j].y=lower(e[j].y));
      if(ans<(f[j]=++t))ans=t;
    }
    for(j=i;j<=n&&e[j].x==e[i].x;j++)if(e[j].y>=0)ins(e[j].y,f[j]);
  }
  return printf("%d",ans),0;
}

  

posted @ 2015-07-01 23:53  Claris  阅读(302)  评论(0编辑  收藏  举报