bzoj 3173 最长上升子序列

Written with StackEdit.

Description

给定一个序列,初始为空。现在我们将\(1\)\(N\)的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?

Input

第一行一个整数\(N\),表示我们要将\(1\)\(N\)插入序列中,接下是\(N\)个数字,第\(k\)个数字\(X_k\),表示我们将\(k\)插入到位置\(X_k(0\leq X_k\leq k-1,1\leq k\leq N)\),

Output

\(N\)行,第\(i\)行表示\(i\)插入\(X_i\)位置后序列的最长上升子序列的长度是多少。

Sample Input

3
0 0 2

Sample Output

1
1
2

HINT

\(100\%\)的数据 \(n\leq100000\).

Solution

  • 如果我们已经得到了最后的序列,我们可以用\(O(nlogn)\)的算法计算出\(LIS\),同时维护\(ans[i]\),表示以\(i\)作为结尾的上升子序列的最大长度.
  • 再令\(g[i]\)表示最终要输出的答案,即插入\(i\)后的\(LIS\)长度.
  • 因为整个序列是从小到大插入的,所以\(g[i]=max_{j=1}^{i}ans[j].\)
  • 使用前缀和优化一下即可.
  • 维护元素的插入可以写一颗平衡树.
#include<bits/stdc++.h>
using namespace std;
typedef long long LoveLive;
inline int read()
{
    int out=0,fh=1;
    char jp=getchar();
    while ((jp>'9'||jp<'0')&&jp!='-')
        jp=getchar();
    if (jp=='-')
        {
            fh=-1;
            jp=getchar();
        }
    while (jp>='0'&&jp<='9')
        {
            out=out*10+jp-'0';
            jp=getchar();
        }
    return out*fh;
}
const int MAXN=1e5+10;
int a[MAXN],qlen=0;
int n;
struct FhqTreap
{
    int x,y;
    struct node
    {
        int lson,rson,siz,weight,key;
    } treap[MAXN];
    int idx,root;
    FhqTreap()
    {
        x=0,y=0;
        idx=0;
        root=0;
        treap[0].key=0;
        treap[0].lson=treap[0].rson=0;
        treap[0].weight=0;
        treap[0].siz=0;
    }
    #define rt treap[o]
    #define ls treap[treap[o].lson]
    #define rs treap[treap[o].rson]
    inline int newnode(int key)
        {
            int o=++idx;
            rt.lson=rt.rson=0;
            rt.siz=1;
            rt.weight=rand();
            rt.key=key;
            return o;
        }
    inline void pushup(int o)
        {
            rt.siz=ls.siz+rs.siz+1;
        }
    int merge(int x,int y)
        {
            if(!x || !y)
                return x+y;
            if(treap[x].weight<treap[y].weight)
                {
                    treap[x].rson=merge(treap[x].rson,y);
                    pushup(x);
                    return x;
                }
            else
                {
                    treap[y].lson=merge(x,treap[y].lson);
                    pushup(y);
                    return y;
                }
        }
    void split(int &x,int &y,int k,int o)
        {
            if(!o)
                x=y=0;
            else
                {
                    if(k<=ls.siz)
                        {
                            y=o;
                            split(x,rt.lson,k,rt.lson);
                        }
                    else
                        {
                            x=o;
                            split(rt.rson,y,k-ls.siz-1,rt.rson);
                        }
                    pushup(o);
                }
        }
    void ins(int key,int pos)
        {
            split(x,y,pos,root);
            y=merge(newnode(key),y);
            root=merge(x,y);
        }
    void dfs(int o)
        {
            if(!o)
                return;
            dfs(rt.lson);
            a[++qlen]=rt.key;
            dfs(rt.rson);
        }
    void getseq()
        {
            dfs(root);
        }
}T;
#define inf 0x7fffffff
int f[MAXN],ans[MAXN];
int main()
{
    srand(19260817);
    n=read();
    for(int i=1;i<=n;++i)
        {
            int pos=read();
            T.ins(i,pos);
        }
    T.getseq();
    memset(f,0x7f,sizeof f);
    f[0]=-inf;
    for(int i=1;i<=n;++i)
        {
            int t=upper_bound(f,f+n+1,a[i])-f;
            f[t]=a[i];
            ans[a[i]]=t;
        }
    for(int i=1;i<=n;++i)
        printf("%d\n",ans[i]=max(ans[i-1],ans[i]));
    puts("");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/jklover/p/10163705.html