[2020多校联考]双端队列xLIS问题

Solution

观察将一个序列按一定方法加入到双端队列的性质。发现若直接在队尾加入,则不会改变相对顺序,而加入到队头的元素实际上是原序列的某个子序列再反过来。干脆直接将原序列复制一份到前面再反转。那么答案就是这个新序列的最长上升子序列(考虑反转过去后,前后对应相等的两个元素不会同时出现在最长上升序列中)。

用树状数组求最长上升子序列即可。

#include<stdio.h>
#include<algorithm>
using namespace std;
#define N 200007

inline int read(){
    int x=0,flag=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

int n,a[N],b[N],f[N],c[N];
inline int max(int x,int y){return x>y? x:y;}
inline int lowbit(int x){return -x&x;}
inline void add(int x,int v){while(x<=n)c[x]=max(c[x],v),x+=lowbit(x);}
inline int query(int x){int ret=0;while(x)ret=max(c[x],ret),x-=lowbit(x);return ret;}

int main(){
    freopen("dequexlis.in","r",stdin);
    freopen("dequexlis.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=b[i]=a[i+n]=read();
    reverse(a+1,a+1+n);
    sort(b+1,b+1+n);
    int sz=unique(b+1,b+1+n)-(b+1),ans=0;
    for(int i=1;i<=n*2;i++){
        int x=lower_bound(b+1,b+1+n,a[i])-b;
        f[i]=query(x-1)+1;
        ans=max(ans,f[i]);
        add(x,f[i]);
    }
    printf("%d",ans);
}
posted @ 2020-11-25 15:47  Kreap  阅读(96)  评论(0编辑  收藏  举报