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\n",ans); }return 0; }
愿你出走半生,归来仍是少年