2019.01.26-bzoj2090: [Poi2010]Monotonicity 2

题目描述:

给出N个正整数a[1..N],再给出K个关系符号(>、<或=)s[1..k]。
选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1]。
求出L的最大值。

算法标签:dp,树状数组

思路:

令f[i]为第i位能最多匹配到的选出的子序列的第几位。然后可以由前向后转移,用树状数组维护,小于和大于的情况,等于的用一个数组维护即可。

讲的不清楚,其实看看代码也能很快理解。

以下代码:

#include<bits/stdc++.h>
#define il inline
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=1e6+5;
char s[5];
int n,k,a[N],b[N],mx,t[2][N],p[N];
il int read(){
    int x,f=1;char ch;
    _(!)ch=='-'?f=-1:f;x=ch^48;
    _()x=(x<<1)+(x<<3)+(ch^48);
    return f*x;
}
il void ins(int op,int x,int v){
    for(;x<=mx;x+=x&-x)t[op][x]=max(v,t[op][x]);
}
il int query(int op,int x){
    int res=0;
    for(;x;x-=x&-x)res=max(res,t[op][x]);
    return res;
}
int main()
{
    n=read();k=read();
    for(int i=1;i<=n;i++)a[i]=read(),mx=max(a[i],mx);
    for(int i=1;i<=k;i++){
        scanf(" %s",s+1);
        if(s[1]=='<')b[i]=1;
        else if(s[1]=='=')b[i]=2;
        else b[i]=3;
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        int x=max(p[a[i]],max(query(0,a[i]-1),query(1,mx-a[i])));
        int y=x%k+1;ans=max(ans,x+1);
        if(b[y]==1)ins(0,a[i],x+1);
        else if(b[y]==2)p[a[i]]=max(p[a[i]],x+1);
        else ins(1,mx-a[i]+1,x+1);
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2019-01-27 09:08  Jessiejzy  阅读(122)  评论(0编辑  收藏  举报