BZOJ 1109 [POI2007]堆积木Klo(树状数组)

【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1109

【题目大意】

  Mary在她的生日礼物中有一些积木。那些积木都是相同大小的立方体。
  每个积木上面都有一个数。Mary用他的所有积木垒了一个高塔。
  妈妈告诉Mary游戏的目的是建一个塔,使得最多的积木在正确的位置。
  一个上面写有数i的积木的正确位置是这个塔从下往上数第i个位置。
  Mary决定从现有的高塔中移走一些,使得有最多的积木在正确的位置。
  请你输出最优答案

【题解】

  我们发现我们需要找到这样序列,i是递增的,a[i]也是递增的,
  i-a[i]是非严格递增的,因为i=a[i]+(i-a[i]),
  因此第一个递增条件是后面两个条件的必要不充分条件,
  这样就是一个二维的LIS,我们按照其中一维排序,用树状数组维护另一维即可。

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring> 
using namespace std;
const int N=100010;
struct data{int x,y;}p[N];
int c[N],n,x,cnt;
bool cmp(data a,data b){
	if(a.x!=b.x)return a.x<b.x;
	else return a.y<b.y;
}
void add(int x,int val){while(x<=n)c[x]=max(c[x],val),x+=x&-x;}
int query(int x){int s=0;while(x)s=max(s,c[x]),x-=x&-x;return s;}
int main(){
    while(~scanf("%d",&n)){
        int ans=cnt=0;
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            if(i-x>=0){p[cnt++]={i-x,x};}
        }sort(p,p+cnt,cmp);
        for(int i=0;i<cnt;i++){
        	int tmp=query(p[i].y-1)+1;
        	ans=max(ans,tmp);
        	add(p[i].y,tmp);
        }printf("%d
",ans);
    }return 0;
}
原文地址:https://www.cnblogs.com/forever97/p/bzoj1109.html