首页 > 代码库 > BZOJ 1109: [POI2007]堆积木Klo

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;}

  

BZOJ 1109: [POI2007]堆积木Klo