BZOJ 1109&&DTOJ 1556 堆積木
阿新 • • 發佈:2018-11-25
BZOJ 1109&&DTOJ 1556 堆積木
題目描述
在她的生日禮物中有一些積木。那些積木都是相同大小的立方體。每個積木上面都有一個數。
用他的所有積木壘了一個高塔。 媽媽告訴
遊戲的目的是建一個塔,使得最多的積木在正確的位置。一個上面寫有數i的積木的正確位置是這個塔從下往上數第
個位置。
決定從現有的高塔中移走一些,使得有最多的積木在正確的位置。請你告訴
她應該移走哪些積木。
輸入
輸入檔案的第一行為一個數
,表示高塔的初始高度。
第二行包含
個數
,表示從下到上每個積木上面的數。
。
輸出
請輸出最多有多少點可以處在正確位置
樣例輸入
5
1 1 2 5 4
樣例輸出
3
題解:
這題很妙(我才不會告訴你我差點就把CDQ打下去了 )
假設有兩個點,
同時在一個合法的序列中,並且
在
的後面,
於是通過瞎膜樣例,得到滿足的條件:
且
因為可以得到,
就是從
號點,走到當前序列起點的消耗。
若
可以滿足,要麼在點
處直接滿足,要麼刪掉一些點後滿足,所以可以得到
很好,三維偏序,
走起。。。
事實並不需要%PoPoQQQ
我們發現
只要滿足
且
,就可以滿足
惹!!
orzorzorzPoPoQQQ
#include<bits/stdc++.h>
using namespace std;
#define in inline
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repd(i,a,b) for(int i=a;i>=b;i--)
#define For(i,a,b) for(int i=a;i<b;i++)
#define _(d) while(d(isdigit(ch=getchar())))
template<class T>in void g(T&t){T x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;t=f*x;}
const int N=1e5+4,M=1e6+4;
struct A{int x,y;}a[N];
int n,mx;
bool cmp(A t1,A t2){
return t1.y<t2.y||(t1.y==t2.y&&t1.x<t2.x);
}
int t[M],f[M];
in void ins(int x,int v){
if(x<0) return;
for(;x<=mx;x+=x&-x) t[x]=max(t[x],v);
}
in int q(int x){
int res=0;
for(;x;x-=x&-x) res=max(res,t[x]);
return res;
}
int main(){
g(n);
rep(i,1,n) g(a[i].x),a[i].y=i-a[i].x,mx=max(mx,a[i].x);
sort(a+1,a+1+n,cmp);int ans=0;
rep(i,1,n){
if(a[i].y<0) continue;
f[i]=q(a[i].x-1)+1;
ins(a[i].x,f[i]);
ans=max(ans,f[i]);
}
return !printf("%d\n",ans);
}