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

  

原文地址:https://www.cnblogs.com/beiyuoi/p/5860366.html