BZOJ 1109: [POI2007]堆积木Klo
Sol
排序+树状数组.
我们要找一个满足下列条件的最长序列.
\(j-w[j]<=i-w[i],j<i,w[j]<w[i]\)
就是维护一个偏序集的最长上升子序列,然后第一个和第三个式子加起来可以推出第二个式子,然后就是二维偏序,用树状数组来维护就可以了.
Code
/************************************************************** Problem: 1109 User: BeiYu Language: C++ Result: Accepted Time:292 ms Memory:2464 kb ****************************************************************/ #include<cstdio> #include<utility> #include<algorithm> #include<iostream> using namespace std; const int N = 100005; #define mpr(a,b) (W){a,b} int n,ans; int d[N]; struct W{ int x,y; }a[N]; bool operator < (const W &a,const W &b){ return a.y==b.y?a.x<b.x:a.y<b.y; } inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; } int Sum(int x,int res=0){ if(!x) return res;for(;x;x-=x&-x) res=max(res,d[x]);return res; } void Add(int x,int v){ for(;x<=n;x+=x&-x) d[x]=max(d[x],v); } int main(){ // freopen("in.in","r",stdin); n=in(); for(int i=1,x;i<=n;i++) x=in(),a[i]=mpr(x,i-x); sort(a+1,a+n+1); for(int i=1;i<=n;i++){ if(a[i].y<0) continue; int tmp=Sum(a[i].x-1)+1; ans=max(tmp,ans); Add(a[i].x,tmp); }cout<<ans<<endl; return 0; }