【bzoj2090】[Poi2010]Monotonicity 2【线段树优化dp】

乱写了一个dp,结果A掉了。。
f [ i ] 表示以 i 结尾的最长长度。
首先 f [ i ] = 1
然后 f [ i ] = m a x { f [ j ] } + 1
j 满足
1. j < i
还有下面这几条的任意一条
2. s [ ( f [ j ] 1 ) % k + 1 ] = , a [ j ] = a [ i ]
3. s [ ( f [ j ] 1 ) % k + 1 ] < , a [ j ] < a [ i ]
4. s [ ( f [ j ] 1 ) % k + 1 ] > , a [ j ] > a [ i ]
这样写能A,貌似是有正确性保证的。
可以写线段树或者树状数组。
线段树

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=500005;
int n,k,ans,a[N],h[N],b[N],f[N];
char str[5];
struct SegmentTree{
    int maxn[N*4];
    void update(int o,int l,int r,int k,int v){
        if(l==r){
            maxn[o]=v;
            return;
        }
        int mid=(l+r)/2;
        if(k<=mid){
            update(o*2,l,mid,k,v);
        }else{
            update(o*2+1,mid+1,r,k,v);
        }
        maxn[o]=max(maxn[o*2],maxn[o*2+1]);
    }
    int query(int o,int l,int r,int L,int R){
        if(L>R){
            return 0;
        }
        if(L==l&&R==r){
            return maxn[o];
        }
        int mid=(l+r)/2;
        if(R<=mid){
            return query(o*2,l,mid,L,R);
        }else if(L>mid){
            return query(o*2+1,mid+1,r,L,R);
        }else{
            return max(query(o*2,l,mid,L,mid),query(o*2+1,mid+1,r,mid+1,R));
        }
    }
}t1,t2,t3;
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        h[++h[0]]=a[i];
    }
    sort(h+1,h+h[0]+1);
    h[0]=unique(h+1,h+h[0]+1)-h-1;
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(h+1,h+h[0]+1,a[i])-h;
    }
    for(int i=1;i<=k;i++){
        scanf("%s",str);
        switch(str[0]){
            case '<':b[i]=0;break;
            case '=':b[i]=1;break;
            case '>':b[i]=2;break;
        }
    }
    for(int i=1;i<=n;i++){
        f[i]=1;
        f[i]=max(f[i],t1.query(1,1,h[0],1,a[i]-1)+1);
        f[i]=max(f[i],t2.query(1,1,h[0],a[i],a[i])+1);
        f[i]=max(f[i],t3.query(1,1,h[0],a[i]+1,h[0])+1);
        if(b[(f[i]-1)%k+1]==0){
            t1.update(1,1,h[0],a[i],f[i]);
        }else if(b[(f[i]-1)%k+1]==1){
            t2.update(1,1,h[0],a[i],f[i]);
        }else{
            t3.update(1,1,h[0],a[i],f[i]);
        }
        ans=max(ans,f[i]);
    }
    printf("%d\n",ans);
    return 0;
}

树状数组

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=500005;
int n,k,ans,a[N],h[N],b[N],f[N],gao[N];
char str[5];
struct BinaryIndexTree{
    int c[N];
    void update(int i,int x){
        while(i<=h[0]){
        c[i]=max(c[i],x);
            i+=i&(-i);
        }
    }
    int query(int i){
        int res=0;
        while(i){
            res=max(res,c[i]);
            i-=i&(-i);
        }
        return res;
    }
}t1,t2;
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        h[++h[0]]=a[i];
    }
    sort(h+1,h+h[0]+1);
    h[0]=unique(h+1,h+h[0]+1)-h-1;
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(h+1,h+h[0]+1,a[i])-h;
    }
    for(int i=1;i<=k;i++){
        scanf("%s",str);
        switch(str[0]){
            case '<':b[i]=0;break;
            case '=':b[i]=1;break;
            case '>':b[i]=2;break;
        }
    }
    for(int i=1;i<=n;i++){
        f[i]=max(f[i],t1.query(a[i]-1)+1);
        f[i]=max(f[i],gao[a[i]]+1);
        f[i]=max(f[i],t2.query(h[0]-a[i])+1);
        if(b[(f[i]-1)%k+1]==0){
            t1.update(a[i],f[i]);
        }else if(b[(f[i]-1)%k+1]==1){
            gao[a[i]]=max(gao[a[i]],f[i]);
        }else{
            t2.update(h[0]-a[i]+1,f[i]);
        }
        ans=max(ans,f[i]);
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ez_2016gdgzoi471/article/details/81840691